diff --git a/macro-project/add-a-com-library-reference-eg-microsoft-scripting-runtime-to-the-vba-project.cs b/macro-project/add-a-com-library-reference-eg-microsoft-scripting-runtime-to-the-vba-project.cs new file mode 100644 index 0000000000..ad5b0f5b55 --- /dev/null +++ b/macro-project/add-a-com-library-reference-eg-microsoft-scripting-runtime-to-the-vba-project.cs @@ -0,0 +1,28 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaReferenceDemo +{ + class Program + { + static void Main() + { + // Create a new workbook (macro-enabled format will be used on save) + Workbook workbook = new Workbook(); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Define the LibID for the Microsoft Scripting Runtime (scrrun.dll) + // The format is: *\G{}##0## + string scriptingLibId = "*\\G{420B2830-E718-11CF-893D-00A0C9054228}#1.0#0#C:\\Windows\\System32\\scrrun.dll#Microsoft Scripting Runtime"; + + // Add the COM library reference to the VBA project + vbaProject.References.AddRegisteredReference("Scripting", scriptingLibId); + + // Save the workbook as a macro-enabled file (XLSM) + workbook.Save("WorkbookWithScriptingReference.xlsm", SaveFormat.Xlsm); + } + } +} \ No newline at end of file diff --git a/macro-project/add-a-custom-reference-to-a-vba-project-that-points-to-a-com-library-installed-on-the-system.cs b/macro-project/add-a-custom-reference-to-a-vba-project-that-points-to-a-com-library-installed-on-the-system.cs new file mode 100644 index 0000000000..19358f3876 --- /dev/null +++ b/macro-project/add-a-custom-reference-to-a-vba-project-that-points-to-a-com-library-installed-on-the-system.cs @@ -0,0 +1,26 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class AddComReference +{ + static void Main() + { + // Create a new workbook (macro-enabled) + Workbook workbook = new Workbook(); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Define the COM library reference (Automation type library) + // Example: Microsoft Scripting Runtime (scrrun.dll) + string referenceName = "Scripting"; + string libid = "*\\G{420B2830-E718-11CF-893D-00A0C9054228}#1.0#0#C:\\Windows\\System32\\scrrun.dll#Scripting Runtime"; + + // Add the reference to the VBA project + vbaProject.References.AddRegisteredReference(referenceName, libid); + + // Save the workbook as a macro-enabled file + workbook.Save("WorkbookWithComReference.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/add-a-module-that-references-external-com-libraries-and-ensure-the-references-compile-correctly.cs b/macro-project/add-a-module-that-references-external-com-libraries-and-ensure-the-references-compile-correctly.cs new file mode 100644 index 0000000000..4b42cb938b --- /dev/null +++ b/macro-project/add-a-module-that-references-external-com-libraries-and-ensure-the-references-compile-correctly.cs @@ -0,0 +1,55 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsComReferenceDemo +{ + public class Program + { + public static void Main() + { + // Create a new workbook (macro-enabled format will be used on save) + Workbook workbook = new Workbook(); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // ------------------------------------------------------------ + // Add a reference to an external COM (Automation) library. + // Here we reference the standard OLE Automation library (stdole). + // ------------------------------------------------------------ + vbaProject.References.AddRegisteredReference( + "stdole", + "*\\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\\Windows\\system32\\stdole2.tlb#OLE Automation"); + + // ------------------------------------------------------------ + // Optionally, add a control reference (e.g., Microsoft Forms 2.0). + // This demonstrates adding a twiddled type library reference. + // ------------------------------------------------------------ + vbaProject.References.AddControlRefrernce( + "MSForms", + "*\\G{0D452EE1-E08F-101A-852E-02608C4D0BB4}#2.0#0#C:\\Windows\\system32\\FM20.DLL#Microsoft Forms 2.0 Object Library", + "twiddledLibid_placeholder", + "extendedLibid_placeholder"); + + // ------------------------------------------------------------ + // Add a new VBA module to the project. + // The module type is Class, and we give it a meaningful name. + // ------------------------------------------------------------ + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Class, "ComHelperModule"); + VbaModule module = vbaProject.Modules[moduleIndex]; + + // Insert VBA code that utilizes the referenced COM library. + // Example: use the stdole library to create a picture object. + module.Codes = @" +Public Sub ShowStdOleMessage() + Dim pic As stdole.StdPicture + MsgBox ""COM library reference is working!"" +End Sub +"; + + // Save the workbook as a macro-enabled file so that the VBA project is retained. + workbook.Save("ComReferenceDemo.xlsm", SaveFormat.Xlsm); + } + } +} \ No newline at end of file diff --git a/macro-project/add-a-reference-to-the-microsoft-outlook-object-library-in-the-vba-project-to-enable-email-automation.cs b/macro-project/add-a-reference-to-the-microsoft-outlook-object-library-in-the-vba-project-to-enable-email-automation.cs new file mode 100644 index 0000000000..cd38f5bd7a --- /dev/null +++ b/macro-project/add-a-reference-to-the-microsoft-outlook-object-library-in-the-vba-project-to-enable-email-automation.cs @@ -0,0 +1,45 @@ +using System; +using System.Text; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaOutlookReference +{ + class Program + { + static void Main() + { + // Create a new workbook (macro-enabled format will be used when saving) + Workbook workbook = new Workbook(); + + // Access the VBA project (automatically created for .xlsm files) + VbaProject vbaProject = workbook.VbaProject; + + // Optional: set project name and encoding + vbaProject.Name = "OutlookAutomationProject"; + vbaProject.Encoding = Encoding.UTF8; + + // Add a reference to the Microsoft Outlook Object Library + // The libid string below is an example for Outlook 16.0; adjust the path/version as needed. + string outlookLibId = "*\\G{00062FFF-0000-0000-C000-000000000046}#9.0#0#C:\\Program Files\\Microsoft Office\\Office16\\MSOUTL.OLB#Microsoft Outlook 16.0 Object Library"; + vbaProject.References.AddRegisteredReference("Outlook", outlookLibId); + + // (Optional) Add a simple VBA module that uses Outlook – just for demonstration + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Class, "EmailHelper"); + vbaProject.Modules[moduleIndex].Codes = + "Sub SendMail()\r\n" + + " Dim olApp As Outlook.Application\r\n" + + " Dim olMail As Outlook.MailItem\r\n" + + " Set olApp = New Outlook.Application\r\n" + + " Set olMail = olApp.CreateItem(0)\r\n" + + " olMail.Subject = \"Test Email\"\r\n" + + " olMail.Body = \"This email was sent from VBA in an Excel workbook.\"\r\n" + + " olMail.Recipients.Add \"example@example.com\"\r\n" + + " olMail.Send\r\n" + + "End Sub"; + + // Save the workbook as a macro-enabled file + workbook.Save("WorkbookWithOutlookReference.xlsm", SaveFormat.Xlsm); + } + } +} \ No newline at end of file diff --git a/macro-project/add-a-reference-to-the-microsoft-xml-v60-library-in-the-vba-project-to-enable-xml-parsing.cs b/macro-project/add-a-reference-to-the-microsoft-xml-v60-library-in-the-vba-project-to-enable-xml-parsing.cs new file mode 100644 index 0000000000..132517e787 --- /dev/null +++ b/macro-project/add-a-reference-to-the-microsoft-xml-v60-library-in-the-vba-project-to-enable-xml-parsing.cs @@ -0,0 +1,29 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class AddMsXmlReference +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Save as a macro‑enabled workbook to ensure a VBA project is created, + // then reload it so the VbaProject property is available. + string tempPath = "temp.xlsm"; + workbook.Save(tempPath, SaveFormat.Xlsm); + workbook = new Workbook(tempPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Add a reference to Microsoft XML, v6.0 (MSXML6) library + vbaProject.References.AddRegisteredReference( + "MSXML2", + "*\\G{88D969C0-F192-11D4-A65F-0040963251E5}#6.0#0#C:\\Windows\\System32\\msxml6.dll#Microsoft XML, v6.0"); + + // Save the workbook with the added reference + workbook.Save("WorkbookWithMsXmlReference.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/add-a-registered-library-reference-to-the-vba-project-using-vbaprojectreferencesaddregisteredreference.cs b/macro-project/add-a-registered-library-reference-to-the-vba-project-using-vbaprojectreferencesaddregisteredreference.cs new file mode 100644 index 0000000000..7313594e06 --- /dev/null +++ b/macro-project/add-a-registered-library-reference-to-the-vba-project-using-vbaprojectreferencesaddregisteredreference.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaReferenceDemo +{ + public class AddRegisteredReferenceDemo + { + public static void Run() + { + try + { + // Create a new workbook (will become macro-enabled when saved as .xlsm) + Workbook workbook = new Workbook(); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add a registered reference to an Automation type library (example: stdole) + vbaProject.References.AddRegisteredReference( + "stdole", + "*\\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\\Windows\\system32\\stdole2.tlb#OLE Automation"); + + // Define output file path + string outputPath = "output.xlsm"; + + // Save the workbook as a macro-enabled file + workbook.Save(outputPath); + Console.WriteLine($"Workbook saved successfully to '{Path.GetFullPath(outputPath)}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + + // Entry point for the application + public static void Main(string[] args) + { + Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/agents.md b/macro-project/agents.md new file mode 100644 index 0000000000..25fc644081 --- /dev/null +++ b/macro-project/agents.md @@ -0,0 +1,116 @@ +--- +category: macro-project +framework: .NET +parent: ../agents.md +version: v2 +--- + +# Persona + +You are a C# developer specializing in VBA projects, macros, and workbook automation using Aspose.Cells for .NET. + +Generate simple, correct, production-quality examples that demonstrate ONE macro-project scenario at a time. + +--- + +# Scope + +- Standalone .cs examples +- One operation per example +- Fully runnable with dotnet run +- No external dependencies + +--- + +# Required Namespaces + +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +--- + +# Key APIs + +- VbaProject +- VbaModule +- Workbook.VbaProject +- VbaProject.Modules +- VbaModuleCollection + +--- + +# Common Pattern + +1. Create workbook +2. Access or create VBA project +3. Add, read, or modify VBA modules +4. Verify project structure +5. Save workbook +6. Print success message + +--- + +# Macro Project Rules + +- Demonstrate one VBA feature per example +- Use meaningful module names +- Keep VBA code samples small and readable +- Focus on project management rather than complex VBA logic + +--- + +# Input Strategy + +- Do NOT rely on external XLSM files +- Create workbook and VBA content programmatically +- Keep examples self-contained + +--- + +# Output Rules + +- Always generate output.xlsm when macros are involved +- Ensure workbook is saved successfully +- Output files are written to the working directory + +--- + +# Common Tasks + +- Create VBA project +- Add VBA module +- Read VBA modules +- Modify VBA code +- Access VBA project information +- Save macro-enabled workbook + +--- + +# Common Mistakes + +❌ var workbook = new Workbook(); +✅ Workbook workbook = new Workbook(); + +❌ Save macro workbook as output.xlsx +✅ Save macro-enabled workbooks as output.xlsm + +❌ Workbook workbook = new Workbook("input.xlsm"); +✅ Workbook workbook = new Workbook(); + +--- + +# Code Simplicity + +- Keep examples concise +- Avoid unnecessary abstractions +- Focus on one VBA capability per example + +--- + +# General Rules + +Refer to the root agents.md for: +- Boundaries +- Testing requirements +- Build and run instructions diff --git a/macro-project/apply-password-protection-only-when-the-workbook-contains-more-than-ten-worksheets-to-enforce-policy.cs b/macro-project/apply-password-protection-only-when-the-workbook-contains-more-than-ten-worksheets-to-enforce-policy.cs new file mode 100644 index 0000000000..64b6821247 --- /dev/null +++ b/macro-project/apply-password-protection-only-when-the-workbook-contains-more-than-ten-worksheets-to-enforce-policy.cs @@ -0,0 +1,37 @@ +using System; +using Aspose.Cells; + +namespace AsposeCellsPasswordPolicy +{ + class Program + { + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Add worksheets to demonstrate the condition (total 12 worksheets) + for (int i = 0; i < 12; i++) + { + // The first worksheet already exists; add new ones for the rest + if (i > 0) + workbook.Worksheets.Add(); + // Optionally put some data + workbook.Worksheets[i].Cells["A1"].PutValue($"Sheet {i + 1}"); + } + + // Apply password protection only if the workbook has more than ten worksheets + if (workbook.Worksheets.Count > 10) + { + // Protect the workbook structure with a password + workbook.Protect(ProtectionType.Structure, "StrongPassword!123"); + } + + // Save the workbook + workbook.Save("ProtectedIfMoreThanTenSheets.xlsx", SaveFormat.Xlsx); + + // Clean up + workbook.Dispose(); + } + } +} \ No newline at end of file diff --git a/macro-project/assign-a-macro-that-calculates-summary-statistics-to-a-shape-object-on-the-worksheet-programmatically.cs b/macro-project/assign-a-macro-that-calculates-summary-statistics-to-a-shape-object-on-the-worksheet-programmatically.cs new file mode 100644 index 0000000000..d24c3ab35f --- /dev/null +++ b/macro-project/assign-a-macro-that-calculates-summary-statistics-to-a-shape-object-on-the-worksheet-programmatically.cs @@ -0,0 +1,31 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; + +namespace AsposeCellsMacroExample +{ + class Program + { + static void Main(string[] args) + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Access the first worksheet + Worksheet worksheet = workbook.Worksheets[0]; + + // Add a rectangle shape to the worksheet (row, column, upperLeftPixel, upperTopPixel, width, height) + Shape shape = worksheet.Shapes.AddRectangle(2, 2, 100, 50, 200, 100); + + // Assign a macro name to the shape. + // The macro "CalculateSummaryStats" should exist in the workbook's VBA project. + shape.MacroName = "CalculateSummaryStats()"; + + // Optional: give the shape a visible name + shape.Name = "StatsButton"; + + // Save the workbook (the macro will be linked to the shape) + workbook.Save("WorkbookWithMacroShape.xlsx", SaveFormat.Xlsx); + } + } +} \ No newline at end of file diff --git a/macro-project/assign-different-macros-to-multiple-form-controls-on-the-same-worksheet-and-verify-each-executes-correctly.cs b/macro-project/assign-different-macros-to-multiple-form-controls-on-the-same-worksheet-and-verify-each-executes-correctly.cs new file mode 100644 index 0000000000..c7230e614c --- /dev/null +++ b/macro-project/assign-different-macros-to-multiple-form-controls-on-the-same-worksheet-and-verify-each-executes-correctly.cs @@ -0,0 +1,66 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; +using Aspose.Cells.Drawing.ActiveXControls; + +namespace AsposeCellsMacroAssignmentDemo +{ + class Program + { + static void Main() + { + // -------------------- Create a new workbook -------------------- + Workbook workbook = new Workbook(); + + // Enable macros for the workbook + workbook.Settings.EnableMacros = true; + + // Get the first worksheet + Worksheet sheet = workbook.Worksheets[0]; + + // -------------------- Add first ActiveX CommandButton -------------------- + // Parameters: control type, upper left row, upper left column, top offset, left offset, width, height + Shape cmdButtonShape1 = sheet.Shapes.AddActiveXControl( + ControlType.CommandButton, 2, 2, 0, 0, 120, 30); + CommandButtonActiveXControl cmdButton1 = (CommandButtonActiveXControl)cmdButtonShape1.ActiveXControl; + cmdButton1.Caption = "Run Macro A"; + // Assign macro name to the shape (not the control) + cmdButtonShape1.MacroName = "MacroA"; + + // -------------------- Add second ActiveX CommandButton -------------------- + Shape cmdButtonShape2 = sheet.Shapes.AddActiveXControl( + ControlType.CommandButton, 5, 2, 0, 0, 120, 30); + CommandButtonActiveXControl cmdButton2 = (CommandButtonActiveXControl)cmdButtonShape2.ActiveXControl; + cmdButton2.Caption = "Run Macro B"; + cmdButtonShape2.MacroName = "MacroB"; + + // -------------------- Add a Forms Button (inherits Shape) -------------------- + Shape formsButton = sheet.Shapes.AddButton(8, 2, 0, 0, 120, 30); + formsButton.Text = "Run Macro C"; + formsButton.MacroName = "MacroC"; + + // -------------------- Verify macro assignments (in‑memory) -------------------- + Console.WriteLine("Macro assigned to first CommandButton: " + cmdButtonShape1.MacroName); + Console.WriteLine("Macro assigned to second CommandButton: " + cmdButtonShape2.MacroName); + Console.WriteLine("Macro assigned to Forms Button: " + formsButton.MacroName); + + // -------------------- Save the workbook -------------------- + string filePath = "MultipleMacrosDemo.xlsm"; + workbook.Save(filePath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved to {filePath}"); + + // -------------------- Load the workbook back and re‑verify -------------------- + Workbook loadedWb = new Workbook(filePath); + Worksheet loadedSheet = loadedWb.Worksheets[0]; + + // Retrieve shapes by index (order of addition) + Shape loadedCmdButtonShape1 = loadedSheet.Shapes[0]; + Shape loadedCmdButtonShape2 = loadedSheet.Shapes[1]; + Shape loadedFormsButton = loadedSheet.Shapes[2]; + + Console.WriteLine("After reload - Macro of first CommandButton: " + loadedCmdButtonShape1.MacroName); + Console.WriteLine("After reload - Macro of second CommandButton: " + loadedCmdButtonShape2.MacroName); + Console.WriteLine("After reload - Macro of Forms Button: " + loadedFormsButton.MacroName); + } + } +} \ No newline at end of file diff --git a/macro-project/attempt-to-unlock-a-vba-project-locked-for-viewing-using-provided-credentials-and-report-the-result.cs b/macro-project/attempt-to-unlock-a-vba-project-locked-for-viewing-using-provided-credentials-and-report-the-result.cs new file mode 100644 index 0000000000..52ce4686aa --- /dev/null +++ b/macro-project/attempt-to-unlock-a-vba-project-locked-for-viewing-using-provided-credentials-and-report-the-result.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaUnlockDemo +{ + class Program + { + static void Main() + { + // Path to the workbook that contains a VBA project locked for viewing + string inputPath = "protected.xlsm"; + + // Path where the unlocked workbook will be saved + string outputPath = "unlocked.xlsm"; + + // Password that should unlock the VBA project + string password = "yourPasswordHere"; + + try + { + // Verify that the input file exists before attempting to load it + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Error: Input file not found: {inputPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + VbaProject vbaProject = workbook.VbaProject; + + // Report current protection status + Console.WriteLine($"Is VBA Project Protected: {vbaProject.IsProtected}"); + + // Validate the supplied password + bool isPasswordValid = vbaProject.ValidatePassword(password); + Console.WriteLine($"Password validation result: {isPasswordValid}"); + + if (isPasswordValid) + { + // Unprotect (unlock) the VBA project + // Passing false for isLockedForViewing and null for password removes protection + vbaProject.Protect(false, null); + Console.WriteLine("VBA project unlocked successfully."); + } + else + { + Console.WriteLine("Failed to unlock VBA project: invalid password."); + } + + // Save the workbook after attempting to unlock + workbook.Save(outputPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved to: {outputPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/automate-signing-of-excel-files-in-continuous-integration-pipeline-to-enforce-macro-security.cs b/macro-project/automate-signing-of-excel-files-in-continuous-integration-pipeline-to-enforce-macro-security.cs new file mode 100644 index 0000000000..1e08735fbd --- /dev/null +++ b/macro-project/automate-signing-of-excel-files-in-continuous-integration-pipeline-to-enforce-macro-security.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +class ExcelMacroSigner +{ + // Signs the VBA project of a macro‑enabled workbook using a digital certificate. + public static void SignWorkbook(string inputPath, string outputPath, string certPath, string certPassword) + { + try + { + // Verify that the input workbook exists. + if (!File.Exists(inputPath)) + throw new FileNotFoundException("Input workbook not found.", inputPath); + + // Verify that the certificate file exists. + if (!File.Exists(certPath)) + throw new FileNotFoundException("Certificate file not found.", certPath); + + // Load the macro‑enabled workbook. + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project; throw if none exists. + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + throw new InvalidOperationException("The workbook does not contain a VBA project."); + + // Load the signing certificate (must contain a private key). + X509Certificate2 certificate = new X509Certificate2(certPath, certPassword); + + // Create a digital signature with comments and the current UTC time. + DigitalSignature digitalSignature = new DigitalSignature(certificate, "CI Pipeline Signature", DateTime.UtcNow); + + // Apply the signature to the VBA project. + vbaProject.Sign(digitalSignature); + + // Save the signed workbook in macro‑enabled format. + workbook.Save(outputPath, SaveFormat.Xlsm); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error signing workbook: {ex.Message}"); + throw; // Re‑throw to allow caller to handle if needed. + } + } + + static void Main() + { + // Paths for input workbook, output signed workbook, and the certificate. + string inputWorkbook = "input.xlsm"; + string signedWorkbook = "signed_output.xlsm"; + string certificatePath = "ci_certificate.pfx"; + string certificatePassword = "yourPassword"; + + try + { + // Perform signing. + SignWorkbook(inputWorkbook, signedWorkbook, certificatePath, certificatePassword); + + // Verify that the signature was applied. + Workbook verificationWorkbook = new Workbook(signedWorkbook); + Console.WriteLine("VBA Project IsSigned: " + verificationWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + verificationWorkbook.VbaProject.IsValidSigned); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unhandled exception: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/batch-export-certificates-from-all-signed-workbooks-in-a-folder-to-a-designated-output-directory.cs b/macro-project/batch-export-certificates-from-all-signed-workbooks-in-a-folder-to-a-designated-output-directory.cs new file mode 100644 index 0000000000..e0d524e813 --- /dev/null +++ b/macro-project/batch-export-certificates-from-all-signed-workbooks-in-a-folder-to-a-designated-output-directory.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; +using System.Security.Cryptography.X509Certificates; + +namespace BatchExportCertificates +{ + class Program + { + static void Main() + { + // Folder containing the workbooks to process + string sourceFolder = @"C:\InputWorkbooks"; + + // Folder where extracted certificates will be saved + string outputFolder = @"C:\ExportedCertificates"; + + // Ensure the output directory exists + Directory.CreateDirectory(outputFolder); + + try + { + // Process each Excel file in the source folder + foreach (string filePath in Directory.GetFiles(sourceFolder, "*.xlsx")) + { + // Verify the file exists before attempting to load + if (!File.Exists(filePath)) + { + Console.WriteLine($"File not found: {filePath}"); + continue; + } + + try + { + // Load the workbook + Workbook workbook = new Workbook(filePath); + + // Skip if the workbook is not digitally signed + if (!workbook.IsDigitallySigned) + { + Console.WriteLine($"Skipping unsigned workbook: {Path.GetFileName(filePath)}"); + continue; + } + + // Retrieve the digital signature collection + DigitalSignatureCollection signatures = workbook.GetDigitalSignature(); + + if (signatures == null) + { + Console.WriteLine($"No signatures collection in: {Path.GetFileName(filePath)}"); + continue; + } + + int certIndex = 0; + + // Iterate through each signature and export its certificate + foreach (DigitalSignature signature in signatures) + { + X509Certificate2 cert = signature.Certificate; + + if (cert == null) + { + Console.WriteLine($"Signature {certIndex} in {Path.GetFileName(filePath)} does not contain a certificate."); + certIndex++; + continue; + } + + // Export the certificate as a .cer file (DER encoded) + byte[] certData = cert.Export(X509ContentType.Cert); + + // Build a unique file name for each exported certificate + string certFileName = $"{Path.GetFileNameWithoutExtension(filePath)}_cert{certIndex}.cer"; + string certPath = Path.Combine(outputFolder, certFileName); + + // Write the certificate bytes to disk + File.WriteAllBytes(certPath, certData); + + Console.WriteLine($"Exported certificate to: {certPath}"); + + certIndex++; + } + } + catch (Exception ex) + { + Console.WriteLine($"Error processing file '{Path.GetFileName(filePath)}': {ex.Message}"); + } + } + + Console.WriteLine("Batch export completed."); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/batch-process-a-folder-of-excel-files-signing-each-vba-project-with-the-same-certificate.cs b/macro-project/batch-process-a-folder-of-excel-files-signing-each-vba-project-with-the-same-certificate.cs new file mode 100644 index 0000000000..1803f73f7b --- /dev/null +++ b/macro-project/batch-process-a-folder-of-excel-files-signing-each-vba-project-with-the-same-certificate.cs @@ -0,0 +1,105 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaBatchSigner +{ + public class VbaBatchSigner + { + /// + /// Signs all VBA projects in macro‑enabled Excel files within a folder using the same certificate. + /// + /// Folder containing the source .xlsm files. + /// Folder where signed files will be saved. + /// Path to the .pfx certificate file. + /// Password for the certificate. + public static void SignVbaProjectsInFolder(string sourceFolder, string outputFolder, string certificatePath, string certificatePassword) + { + // Verify certificate file exists + if (!File.Exists(certificatePath)) + { + Console.WriteLine($"Certificate file not found: {certificatePath}"); + return; + } + + X509Certificate2 certificate; + try + { + // Load the signing certificate once + certificate = new X509Certificate2(certificatePath, certificatePassword); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load certificate: {ex.Message}"); + return; + } + + // Create a DigitalSignature instance that will be reused for each workbook + DigitalSignature digitalSignature = new DigitalSignature(certificate, "Batch VBA Signature", DateTime.Now); + + // Ensure the output directory exists + if (!Directory.Exists(outputFolder)) + { + Directory.CreateDirectory(outputFolder); + } + + // Process each .xlsm file in the source folder + foreach (string filePath in Directory.GetFiles(sourceFolder, "*.xlsm")) + { + if (!File.Exists(filePath)) + { + Console.WriteLine($"Source file not found (skipped): {filePath}"); + continue; + } + + try + { + // Load the workbook (macro‑enabled) + Workbook workbook = new Workbook(filePath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // If a VBA project exists, sign it + if (vbaProject != null) + { + vbaProject.Sign(digitalSignature); + } + + // Determine output file path (preserve original file name) + string outputFilePath = Path.Combine(outputFolder, Path.GetFileName(filePath)); + + // Save the signed workbook as macro‑enabled format + workbook.Save(outputFilePath, SaveFormat.Xlsm); + } + catch (Exception ex) + { + Console.WriteLine($"Error processing file '{filePath}': {ex.Message}"); + } + } + } + + // Example usage + public static void Main() + { + try + { + string sourceFolder = @"C:\ExcelFiles\Source"; + string outputFolder = @"C:\ExcelFiles\Signed"; + string certPath = @"C:\Certificates\mycert.pfx"; + string certPassword = "certPassword"; + + SignVbaProjectsInFolder(sourceFolder, outputFolder, certPath, certPassword); + + Console.WriteLine("Batch signing completed."); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/batch-process-a-folder-of-macro-enabled-workbooks-adding-a-printing-prevention-macro-to-each-file.cs b/macro-project/batch-process-a-folder-of-macro-enabled-workbooks-adding-a-printing-prevention-macro-to-each-file.cs new file mode 100644 index 0000000000..80cac51037 --- /dev/null +++ b/macro-project/batch-process-a-folder-of-macro-enabled-workbooks-adding-a-printing-prevention-macro-to-each-file.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class BatchAddPrintPreventionMacro +{ + static void Main() + { + try + { + // Folder containing macro‑enabled workbooks (*.xlsm) + string folderPath = @"C:\Path\To\MacroWorkbooks"; + + // Verify that the folder exists + if (!Directory.Exists(folderPath)) + { + Console.WriteLine($"Folder not found: {folderPath}"); + return; + } + + // Get all .xlsm files in the folder + string[] files = Directory.GetFiles(folderPath, "*.xlsm", SearchOption.TopDirectoryOnly); + + foreach (string file in files) + { + // Ensure the file still exists before processing + if (!File.Exists(file)) + { + Console.WriteLine($"File not found (skipped): {file}"); + continue; + } + + try + { + // Load the workbook (macro‑enabled) + Workbook workbook = new Workbook(file); + + // Ensure the workbook has a VBA project; if not, create one by saving as .xlsm and reloading + if (workbook.VbaProject == null || workbook.VbaProject.Modules.Count == 0) + { + workbook.Save(file, SaveFormat.Xlsm); + workbook = new Workbook(file); + } + + // Locate the ThisWorkbook module (where workbook events are placed) + int thisWorkbookIndex = -1; + for (int i = 0; i < workbook.VbaProject.Modules.Count; i++) + { + if (workbook.VbaProject.Modules[i].Name.Equals("ThisWorkbook", StringComparison.OrdinalIgnoreCase)) + { + thisWorkbookIndex = i; + break; + } + } + + // If ThisWorkbook module does not exist, add it as a class module + if (thisWorkbookIndex == -1) + { + thisWorkbookIndex = workbook.VbaProject.Modules.Add(VbaModuleType.Class, "ThisWorkbook"); + } + + // Insert the Workbook_BeforePrint event to cancel printing + VbaModule thisWorkbookModule = workbook.VbaProject.Modules[thisWorkbookIndex]; + thisWorkbookModule.Codes = +@"Private Sub Workbook_BeforePrint(Cancel As Boolean) + MsgBox ""Printing is disabled by policy."" + Cancel = True +End Sub"; + + // Save the modified workbook back to the same file (keep macro format) + workbook.Save(file, SaveFormat.Xlsm); + Console.WriteLine($"Processed: {Path.GetFileName(file)}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error processing file '{file}': {ex.Message}"); + } + } + + Console.WriteLine("Processing completed. Printing‑prevention macro added to all workbooks."); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/batch-process-workbooks-to-add-a-standard-library-reference-then-generate-a-summary-of-successes-and-failures.cs b/macro-project/batch-process-workbooks-to-add-a-standard-library-reference-then-generate-a-summary-of-successes-and-failures.cs new file mode 100644 index 0000000000..c9bf7d1837 --- /dev/null +++ b/macro-project/batch-process-workbooks-to-add-a-standard-library-reference-then-generate-a-summary-of-successes-and-failures.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Folder containing the workbooks to process + string sourceFolder = "InputWorkbooks"; + // Folder where processed workbooks will be saved + string outputFolder = "OutputWorkbooks"; + + // Ensure the output folder exists + Directory.CreateDirectory(outputFolder); + + // Get all macro-enabled workbooks in the source folder + string[] files = Directory.GetFiles(sourceFolder, "*.xlsm", SearchOption.TopDirectoryOnly); + + int successCount = 0; + int failureCount = 0; + + foreach (string filePath in files) + { + try + { + // Load the workbook from file + Workbook workbook = new Workbook(filePath); + + // Add the standard library reference if a VBA project is present + if (workbook.VbaProject != null) + { + workbook.VbaProject.References.AddRegisteredReference( + "stdole", + "*\\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\\Windows\\system32\\stdole2.tlb#OLE Automation"); + } + + // Determine the output file path (overwrite in the output folder) + string fileName = Path.GetFileName(filePath); + string outputPath = Path.Combine(outputFolder, fileName); + + // Save the workbook preserving the macro-enabled format + workbook.Save(outputPath, SaveFormat.Xlsm); + + successCount++; + } + catch (Exception ex) + { + // Log the error and continue with the next file + Console.WriteLine($"Error processing '{filePath}': {ex.Message}"); + failureCount++; + } + } + + // Output a summary of the batch operation + Console.WriteLine($"Batch processing completed. Successes: {successCount}, Failures: {failureCount}"); + } +} \ No newline at end of file diff --git a/macro-project/batch-validate-signatures-of-multiple-workbooks-and-generate-a-summary-report-of-validation-statuses.cs b/macro-project/batch-validate-signatures-of-multiple-workbooks-and-generate-a-summary-report-of-validation-statuses.cs new file mode 100644 index 0000000000..79e2b7a808 --- /dev/null +++ b/macro-project/batch-validate-signatures-of-multiple-workbooks-and-generate-a-summary-report-of-validation-statuses.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace SignatureBatchValidator +{ + class Program + { + static void Main(string[] args) + { + // Define the workbook files to validate. + // In a real scenario you might read these from a directory or input arguments. + string[] workbookPaths = new string[] + { + "Workbook1.xlsx", + "Workbook2.xlsx", + "Workbook3.xlsx" + }; + + // List to hold summary lines. + List reportLines = new List(); + reportLines.Add("FileName,IsSigned,SignatureCount,ValidSignatureCount"); + + foreach (string path in workbookPaths) + { + // Load the workbook using the provided constructor (load rule). + Workbook wb = new Workbook(path); + + // Determine if the workbook is digitally signed. + bool isSigned = wb.IsDigitallySigned; + + int signatureCount = 0; + int validSignatureCount = 0; + + if (isSigned) + { + // Retrieve the digital signature collection (method rule). + DigitalSignatureCollection signatures = wb.GetDigitalSignature(); + + if (signatures != null) + { + foreach (DigitalSignature sig in signatures) + { + signatureCount++; + // Check each signature's validity (property rule). + if (sig.IsValid) + { + validSignatureCount++; + } + } + } + } + + // Build a CSV line for the current workbook. + string fileName = Path.GetFileName(path); + string line = $"{fileName},{isSigned},{signatureCount},{validSignatureCount}"; + reportLines.Add(line); + } + + // Write the summary report to a text file. + string reportPath = "SignatureSummary.txt"; + File.WriteAllLines(reportPath, reportLines); + + Console.WriteLine($"Signature validation summary written to: {reportPath}"); + } + } +} \ No newline at end of file diff --git a/macro-project/check-if-the-vba-project-is-locked-for-viewing-before-extracting-macros.cs b/macro-project/check-if-the-vba-project-is-locked-for-viewing-before-extracting-macros.cs new file mode 100644 index 0000000000..beabb948e3 --- /dev/null +++ b/macro-project/check-if-the-vba-project-is-locked-for-viewing-before-extracting-macros.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaCheck +{ + class Program + { + static void Main(string[] args) + { + // Path to the Excel file (macro-enabled) + string inputPath = "sample.xlsm"; + + // Load the workbook (uses Aspose.Cells load rule) + Workbook workbook = new Workbook(inputPath); + + // Check if the workbook contains any VBA/macros + if (!workbook.HasMacro) + { + Console.WriteLine("The workbook does not contain any macros."); + return; + } + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Verify whether the VBA project is locked for viewing + if (vbaProject.IslockedForViewing) + { + Console.WriteLine("The VBA project is locked for viewing. Cannot extract macros."); + return; + } + + // The project is not locked; proceed to extract macro code from each module + Console.WriteLine("Extracting macros..."); + + // Ensure the output directory exists + string outputDir = "ExtractedMacros"; + Directory.CreateDirectory(outputDir); + + // Iterate through all VBA modules + for (int i = 0; i < vbaProject.Modules.Count; i++) + { + VbaModule module = vbaProject.Modules[i]; + string moduleName = module.Name; + string moduleCode = module.Codes; + + // Save each module's code to a separate .bas file + string filePath = Path.Combine(outputDir, $"{moduleName}.bas"); + File.WriteAllText(filePath, moduleCode); + + Console.WriteLine($"Module '{moduleName}' extracted to '{filePath}'."); + } + + Console.WriteLine("Macro extraction completed."); + } + } +} \ No newline at end of file diff --git a/macro-project/check-the-issigned-property-after-adding-a-digital-signature-to-a-vba-project-programmatically.cs b/macro-project/check-the-issigned-property-after-adding-a-digital-signature-to-a-vba-project-programmatically.cs new file mode 100644 index 0000000000..8e02f05c32 --- /dev/null +++ b/macro-project/check-the-issigned-property-after-adding-a-digital-signature-to-a-vba-project-programmatically.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +class CheckVbaSignature +{ + static void Main() + { + try + { + // Create a new macro‑enabled workbook + Workbook workbook = new Workbook(); + + // Add a VBA module to initialise the VBA project + int moduleIndex = workbook.VbaProject.Modules.Add(VbaModuleType.Class, "DemoModule"); + workbook.VbaProject.Modules[moduleIndex].Codes = + "Sub Demo()\r\n MsgBox \"Hello\"\r\nEnd Sub"; + + // Path and password for the signing certificate + string certPath = "mycert.pfx"; + string certPassword = "certPassword"; + + // Load the certificate and sign the VBA project if the file exists + if (File.Exists(certPath) && workbook.VbaProject != null) + { + try + { + // Load certificate (obsolete warning suppressed, still functional) + X509Certificate2 certificate = new X509Certificate2(certPath, certPassword); + DigitalSignature vbaSignature = new DigitalSignature(certificate, "VBA Signature", DateTime.Now); + workbook.VbaProject.Sign(vbaSignature); + Console.WriteLine("VBA project signed successfully."); + } + catch (CryptographicException ex) + { + Console.WriteLine($"Failed to load certificate: {ex.Message}"); + Console.WriteLine("Proceeding without signing the VBA project."); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error during signing: {ex.Message}"); + } + } + else + { + Console.WriteLine("Certificate file not found or VBA project unavailable. Skipping VBA signing."); + } + + // Save the workbook to a memory stream in macro‑enabled format + using (MemoryStream stream = new MemoryStream()) + { + workbook.Save(stream, SaveFormat.Xlsm); + stream.Position = 0; // Reset for reading + + // Reload the workbook to verify signature persistence + Workbook reloadedWorkbook = new Workbook(stream); + Console.WriteLine("VBA Project IsSigned: " + reloadedWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + reloadedWorkbook.VbaProject.IsValidSigned); + } + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/clear-existing-code-from-a-specific-module-and-insert-updated-macro-logic-from-an-external-source.cs b/macro-project/clear-existing-code-from-a-specific-module-and-insert-updated-macro-logic-from-an-external-source.cs new file mode 100644 index 0000000000..8073cae347 --- /dev/null +++ b/macro-project/clear-existing-code-from-a-specific-module-and-insert-updated-macro-logic-from-an-external-source.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroUpdate +{ + public class MacroUpdater + { + public static void Run() + { + // Paths for the source workbook, external macro file, and the output workbook + string sourceWorkbookPath = "input.xlsm"; + string externalMacroPath = "newMacro.bas"; + string outputWorkbookPath = "output.xlsm"; + + // Name of the VBA module to be replaced + string targetModuleName = "TargetModule"; + + try + { + // Verify source workbook exists + if (!File.Exists(sourceWorkbookPath)) + throw new FileNotFoundException($"Source workbook not found: {sourceWorkbookPath}"); + + // Verify external macro file exists + if (!File.Exists(externalMacroPath)) + throw new FileNotFoundException($"Macro file not found: {externalMacroPath}"); + + // Load the macro‑enabled workbook + Workbook workbook = new Workbook(sourceWorkbookPath); + + // Access the VBA project and its module collection + VbaProject vbaProject = workbook.VbaProject; + VbaModuleCollection modules = vbaProject.Modules; + + // Remove the existing module with the specified name, if it exists + try + { + modules.Remove(targetModuleName); + } + catch + { + // Ignore if the module does not exist + } + + // Add a new procedural module with the same name + int newModuleIndex = modules.Add(VbaModuleType.Procedural, targetModuleName); + VbaModule newModule = modules[newModuleIndex]; + + // Read the updated macro code from the external file + string updatedMacroCode = File.ReadAllText(externalMacroPath); + + // Insert the new macro code into the module + newModule.Codes = updatedMacroCode; + + // Save the workbook as a macro‑enabled file + workbook.Save(outputWorkbookPath, SaveFormat.Xlsm); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error updating macro: {ex.Message}"); + } + } + } + + // Entry point for the application + public class Program + { + public static void Main(string[] args) + { + MacroUpdater.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/clone-a-workbook-duplicate-its-vba-project-and-save-the-clone-as-a-separate-xlsm-file.cs b/macro-project/clone-a-workbook-duplicate-its-vba-project-and-save-the-clone-as-a-separate-xlsm-file.cs new file mode 100644 index 0000000000..a39e4dd635 --- /dev/null +++ b/macro-project/clone-a-workbook-duplicate-its-vba-project-and-save-the-clone-as-a-separate-xlsm-file.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace WorkbookCloneApp +{ + class Program + { + static void Main() + { + const string sourcePath = "source.xlsm"; + const string clonePath = "clone.xlsm"; + + try + { + // Ensure the source file exists before loading + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: {sourcePath}"); + return; + } + + // Load the source workbook that contains VBA macros + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Create an empty workbook that will hold the clone + Workbook clonedWorkbook = new Workbook(); + + // Configure copy options to retain macros/VBA project + CopyOptions copyOptions = new CopyOptions + { + KeepMacros = true + }; + + // Copy all contents from the source workbook to the clone + sourceWorkbook.Copy(clonedWorkbook, copyOptions); + + // Explicitly duplicate the VBA project (optional, ensures full copy) + clonedWorkbook.VbaProject.Copy(sourceWorkbook.VbaProject); + + // Save the cloned workbook as a macro‑enabled file + clonedWorkbook.Save(clonePath, SaveFormat.Xlsm); + + Console.WriteLine($"Workbook cloned successfully to {clonePath}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/compare-exported-certificate-files-with-original-certificates-to-detect-any-corruption-during-export.cs b/macro-project/compare-exported-certificate-files-with-original-certificates-to-detect-any-corruption-during-export.cs new file mode 100644 index 0000000000..41f5357adb --- /dev/null +++ b/macro-project/compare-exported-certificate-files-with-original-certificates-to-detect-any-corruption-during-export.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +class CompareCertificates +{ + static void Main() + { + try + { + // Paths to the original certificate and the signed workbook + string originalCertPath = "original.pfx"; + string certPassword = "password"; + string signedWorkbookPath = "signed.xlsx"; + + // Verify that the certificate file exists + if (!File.Exists(originalCertPath)) + { + Console.WriteLine($"Certificate file not found: {originalCertPath}"); + return; + } + + // Load the original certificate (including private key) + X509Certificate2 originalCert = new X509Certificate2(originalCertPath, certPassword); + // Export the original certificate to a byte array for later comparison + byte[] originalRawData = originalCert.Export(X509ContentType.Pkcs12); + + // Create a new workbook and add some content + Workbook workbook = new Workbook(); + workbook.Worksheets[0].Cells["A1"].PutValue("Signed Workbook"); + + // Create a digital signature using the original certificate + DigitalSignature signature = new DigitalSignature(originalCert, "Demo Signature", DateTime.Now); + + // Add the digital signature to a collection and attach it to the workbook + DigitalSignatureCollection signatureCollection = new DigitalSignatureCollection(); + signatureCollection.Add(signature); + workbook.AddDigitalSignature(signatureCollection); + + // Save the signed workbook + workbook.Save(signedWorkbookPath, SaveFormat.Xlsx); + + // Verify that the signed workbook was created + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"Failed to create signed workbook: {signedWorkbookPath}"); + return; + } + + // Load the signed workbook and retrieve its digital signatures + Workbook signedWorkbook = new Workbook(signedWorkbookPath); + DigitalSignatureCollection loadedSignatures = signedWorkbook.GetDigitalSignature(); + + // Compare each exported certificate with the original one + foreach (DigitalSignature loadedSignature in loadedSignatures) + { + X509Certificate2 exportedCert = loadedSignature.Certificate; + byte[] exportedRawData = exportedCert.Export(X509ContentType.Pkcs12); + + bool certificatesMatch = AreByteArraysEqual(originalRawData, exportedRawData); + Console.WriteLine($"Certificate match: {certificatesMatch}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + + // Helper method to compare two byte arrays + static bool AreByteArraysEqual(byte[] a, byte[] b) + { + if (a == null || b == null) return false; + if (a.Length != b.Length) return false; + for (int i = 0; i < a.Length; i++) + { + if (a[i] != b[i]) return false; + } + return true; + } +} \ No newline at end of file diff --git a/macro-project/compare-exported-certificate-thumbprint-with-original-certificate-thumbprint-to-ensure-integrity.cs b/macro-project/compare-exported-certificate-thumbprint-with-original-certificate-thumbprint-to-ensure-integrity.cs new file mode 100644 index 0000000000..5c8a56bcad --- /dev/null +++ b/macro-project/compare-exported-certificate-thumbprint-with-original-certificate-thumbprint-to-ensure-integrity.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsExamples +{ + public class CertificateThumbprintVerificationDemo + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + + public static void Run() + { + // Path to the certificate (PFX) and its password + string certPath = "mycert.pfx"; + string certPassword = "certPassword"; + + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load the original certificate that will be used for signing + X509Certificate2 originalCertificate = new X509Certificate2(certPath, certPassword); + string originalThumbprint = originalCertificate.Thumbprint; + Console.WriteLine($"Original Certificate Thumbprint: {originalThumbprint}"); + + // ------------------------------------------------- + // Create a new workbook and add some sample data + // ------------------------------------------------- + Workbook workbook = new Workbook(); // create + Worksheet sheet = workbook.Worksheets[0]; + sheet.Cells["A1"].PutValue("Document to be digitally signed"); + + // ------------------------------------------------- + // Create a digital signature using the original certificate + // ------------------------------------------------- + DigitalSignature signature = new DigitalSignature(originalCertificate, "Signed by Aspose", DateTime.Now); + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + signatures.Add(signature); + + // Add the digital signature to the workbook + workbook.AddDigitalSignature(signatures); // add digital signature + + // Save the signed workbook + string signedPath = "SignedWorkbook.xlsx"; + workbook.Save(signedPath); // save + Console.WriteLine($"Signed workbook saved to: {signedPath}"); + + // ------------------------------------------------- + // Load the signed workbook and verify the certificate thumbprint + // ------------------------------------------------- + if (!File.Exists(signedPath)) + { + Console.WriteLine($"Signed workbook not found: {signedPath}"); + return; + } + + Workbook signedWorkbook = new Workbook(signedPath); // load + DigitalSignatureCollection loadedSignatures = signedWorkbook.GetDigitalSignature(); + + foreach (DigitalSignature loadedSignature in loadedSignatures) + { + // Get the certificate from the loaded signature + X509Certificate2 loadedCertificate = loadedSignature.Certificate; + string loadedThumbprint = loadedCertificate?.Thumbprint; + + Console.WriteLine($"Loaded Signature Thumbprint: {loadedThumbprint}"); + + // Compare thumbprints + bool isThumbprintMatch = string.Equals(originalThumbprint, loadedThumbprint, StringComparison.OrdinalIgnoreCase); + Console.WriteLine($"Thumbprint match: {isThumbprintMatch}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/confirm-that-the-exported-certificate-file-size-matches-the-expected-length.cs b/macro-project/confirm-that-the-exported-certificate-file-size-matches-the-expected-length.cs new file mode 100644 index 0000000000..7cc6d98914 --- /dev/null +++ b/macro-project/confirm-that-the-exported-certificate-file-size-matches-the-expected-length.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class VerifyExportedCertificateSizeDemo + { + public static void Run() + { + try + { + // Path to the workbook that contains a signed VBA project + string signedWorkbookPath = "SignedWithVba.xlsm"; + + // Ensure the file exists before proceeding + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"File not found: {signedWorkbookPath}"); + return; + } + + // Load the signed workbook + Workbook workbook = new Workbook(signedWorkbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is actually signed + if (!vbaProject.IsSigned) + { + Console.WriteLine("The VBA project is not signed. No certificate to export."); + return; + } + + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + // Guard against null or empty data + if (certData == null || certData.Length == 0) + { + Console.WriteLine("Certificate raw data is empty."); + return; + } + + // Define the output certificate file path + string certFilePath = "ExportedVbaCertificate.cer"; + + // Write the certificate bytes to a file + File.WriteAllBytes(certFilePath, certData); + Console.WriteLine($"Certificate exported to: {certFilePath}"); + + // Get the file size of the exported certificate + long fileSize = new FileInfo(certFilePath).Length; + + // Compare the file size with the original byte array length + bool sizesMatch = fileSize == certData.Length; + + // Output the verification result + Console.WriteLine($"Original certificate byte length: {certData.Length}"); + Console.WriteLine($"Exported file size (bytes): {fileSize}"); + Console.WriteLine($"Sizes match: {sizesMatch}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + public class Program + { + public static void Main(string[] args) + { + VerifyExportedCertificateSizeDemo.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/copy-a-macro-that-generates-charts-from-a-template-workbook-to-multiple-target-workbooks-in-a-loop.cs b/macro-project/copy-a-macro-that-generates-charts-from-a-template-workbook-to-multiple-target-workbooks-in-a-loop.cs new file mode 100644 index 0000000000..f67971c389 --- /dev/null +++ b/macro-project/copy-a-macro-that-generates-charts-from-a-template-workbook-to-multiple-target-workbooks-in-a-loop.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroCopyExample +{ + class Program + { + static void Main() + { + // Path to the template workbook that contains the macro which creates charts + string templatePath = "TemplateWithMacro.xlsm"; + + // Load the template workbook (macro-enabled) + Workbook templateWorkbook = new Workbook(templatePath); + + // List of target workbook file names (output files) + List targetFiles = new List + { + "Target1.xlsm", + "Target2.xlsm", + "Target3.xlsm" + // Add more target file names as needed + }; + + // Loop through each target workbook, copy the VBA project (macro) from the template, + // and save the result as a macro‑enabled workbook. + foreach (string targetPath in targetFiles) + { + // Create an empty workbook + Workbook targetWorkbook = new Workbook(); + + // Enable macros for the target workbook (optional but clarifies intent) + targetWorkbook.Settings.EnableMacros = true; + + // Copy the entire VBA project (including modules, references, etc.) from the template + targetWorkbook.VbaProject.Copy(templateWorkbook.VbaProject); + + // Save the target workbook as a macro‑enabled file + targetWorkbook.Save(targetPath, SaveFormat.Xlsm); + } + + Console.WriteLine("Macro copied to all target workbooks successfully."); + } + } +} \ No newline at end of file diff --git a/macro-project/copy-a-vba-module-from-one-workbook-to-another-preserving-its-original-code-and-attributes.cs b/macro-project/copy-a-vba-module-from-one-workbook-to-another-preserving-its-original-code-and-attributes.cs new file mode 100644 index 0000000000..6925b22638 --- /dev/null +++ b/macro-project/copy-a-vba-module-from-one-workbook-to-another-preserving-its-original-code-and-attributes.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsDemo +{ + public class CopyVbaModuleDemo + { + public static void Run() + { + try + { + const string sourcePath = "source.xlsm"; + const string destPath = "dest.xlsm"; + + // Verify source file exists + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: {sourcePath}"); + return; + } + + // Load the source workbook that already contains the VBA module + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Ensure the source workbook has a VBA project with at least one module + if (sourceWorkbook.VbaProject == null || sourceWorkbook.VbaProject.Modules.Count == 0) + { + Console.WriteLine("Source workbook does not contain any VBA modules."); + return; + } + + // Access the first VBA module in the source workbook + VbaModule sourceModule = sourceWorkbook.VbaProject.Modules[0]; + + // Create a new (empty) destination workbook + Workbook destWorkbook = new Workbook(); + + // Add a new module to the destination workbook with the same type and name as the source module + int destModuleIndex = destWorkbook.VbaProject.Modules.Add(sourceModule.Type, sourceModule.Name); + VbaModule destModule = destWorkbook.VbaProject.Modules[destModuleIndex]; + + // Copy the VBA code from the source module to the destination module + destModule.Codes = sourceModule.Codes; + + // Save the destination workbook as a macro‑enabled file to preserve the VBA project + destWorkbook.Save(destPath, SaveFormat.Xlsm); + Console.WriteLine($"Destination workbook saved successfully: {destPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + public class Program + { + public static void Main(string[] args) + { + CopyVbaModuleDemo.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/copy-all-macros-from-a-source-workbook-to-a-destination-workbook-while-preserving-macro-security-settings.cs b/macro-project/copy-all-macros-from-a-source-workbook-to-a-destination-workbook-while-preserving-macro-security-settings.cs new file mode 100644 index 0000000000..adaf810517 --- /dev/null +++ b/macro-project/copy-all-macros-from-a-source-workbook-to-a-destination-workbook-while-preserving-macro-security-settings.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsExamples +{ + public class CopyMacrosDemo + { + public static void Main() + { + Run(); + } + + public static void Run() + { + try + { + const string sourcePath = "source_with_macros.xlsm"; + const string destPath = "destination_with_macros.xlsm"; + + // Verify source file exists to avoid FileNotFoundException + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: {sourcePath}"); + return; + } + + // Load the source workbook that contains macros (must be a macro-enabled file) + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Create an empty destination workbook + Workbook destWorkbook = new Workbook(); + + // Preserve the macro security setting from the source workbook + destWorkbook.Settings.EnableMacros = sourceWorkbook.Settings.EnableMacros; + + // Set copy options to keep macros during the copy operation + CopyOptions options = new CopyOptions + { + KeepMacros = true + }; + + // Copy the entire source workbook (including macros) into the destination workbook + sourceWorkbook.Copy(destWorkbook, options); + + // Save the destination workbook as a macro-enabled file + destWorkbook.Save(destPath); + Console.WriteLine($"Destination workbook saved successfully: {destPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/copy-userform-designerstorage-from-a-template-workbook-to-a-target-workbook-preserving-layout.cs b/macro-project/copy-userform-designerstorage-from-a-template-workbook-to-a-target-workbook-preserving-layout.cs new file mode 100644 index 0000000000..3be35dd6bc --- /dev/null +++ b/macro-project/copy-userform-designerstorage-from-a-template-workbook-to-a-target-workbook-preserving-layout.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class CopyUserFormDesignerStorage +{ + static void Main() + { + try + { + // Paths for the template, target, and output workbooks + string templatePath = "TemplateWithUserForm.xlsm"; + string targetPath = "TargetWorkbook.xlsm"; + string outputPath = "TargetWorkbook_WithUserForm.xlsm"; + + // Verify that the template file exists + if (!File.Exists(templatePath)) + { + Console.WriteLine($"Template file not found: {templatePath}"); + return; + } + + // Load the template workbook that contains the UserForm + Workbook templateWb = new Workbook(templatePath); + + // Load the target workbook if it exists; otherwise create a new workbook + Workbook targetWb = File.Exists(targetPath) ? new Workbook(targetPath) : new Workbook(); + + // Name of the UserForm to copy (adjust if different) + string userFormName = "UserForm1"; + + // ----- Retrieve the designer storage (binary .frx data) from the template ----- + byte[] designerStorage = templateWb.VbaProject.Modules.GetDesignerStorage(userFormName); + + // ----- Locate the module that holds the UserForm's VBA code ----- + int sourceModuleIndex = -1; + for (int i = 0; i < templateWb.VbaProject.Modules.Count; i++) + { + if (templateWb.VbaProject.Modules[i].Name.Equals(userFormName, StringComparison.OrdinalIgnoreCase)) + { + sourceModuleIndex = i; + break; + } + } + + if (sourceModuleIndex == -1) + { + Console.WriteLine($"UserForm '{userFormName}' not found in the template workbook."); + return; + } + + // Extract the VBA code (the .bas part) from the source module + string userFormCode = templateWb.VbaProject.Modules[sourceModuleIndex].Codes; + + // ----- Add the UserForm to the target workbook's VBA project ----- + int addedIndex = targetWb.VbaProject.Modules.AddUserForm(userFormName, userFormCode, designerStorage); + Console.WriteLine($"UserForm added to target workbook at module index: {addedIndex}"); + + // Save the target workbook (preserving macros and the newly added UserForm) + targetWb.Save(outputPath); + Console.WriteLine($"Target workbook saved successfully as '{outputPath}'."); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/create-a-macro-that-iterates-through-all-worksheets-and-logs-each-sheet-name-using-the-new-module.cs b/macro-project/create-a-macro-that-iterates-through-all-worksheets-and-logs-each-sheet-name-using-the-new-module.cs new file mode 100644 index 0000000000..bc10b59d47 --- /dev/null +++ b/macro-project/create-a-macro-that-iterates-through-all-worksheets-and-logs-each-sheet-name-using-the-new-module.cs @@ -0,0 +1,35 @@ +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Add sample worksheets (optional, for demonstration) + workbook.Worksheets[0].Name = "Sheet1"; + workbook.Worksheets.Add("Sheet2"); + workbook.Worksheets.Add("Sheet3"); + + // Add a new VBA module to the workbook + VbaProject vbaProject = workbook.VbaProject; + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Procedural, "LogModule"); + VbaModule module = vbaProject.Modules[moduleIndex]; + + // VBA macro that iterates through all worksheets and logs each sheet name + string vbaCode = @" +Sub LogSheetNames() + Dim ws As Worksheet + For Each ws In ThisWorkbook.Worksheets + Debug.Print ws.Name + Next ws +End Sub +"; + module.Codes = vbaCode; + + // Save the workbook as a macro‑enabled file + workbook.Save("LogSheetNames.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/create-a-new-vba-module-named-automation-within-the-vbaproject.cs b/macro-project/create-a-new-vba-module-named-automation-within-the-vbaproject.cs new file mode 100644 index 0000000000..9c79cd1b7d --- /dev/null +++ b/macro-project/create-a-new-vba-module-named-automation-within-the-vbaproject.cs @@ -0,0 +1,27 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Access the VBA project of the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add a procedural VBA module named "Automation" + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Procedural, "Automation"); + + // Retrieve the newly added module + VbaModule automationModule = vbaProject.Modules[moduleIndex]; + + // (Optional) Add some VBA code to the module + automationModule.Codes = "Sub AutomationMacro()\n MsgBox \"Automation module loaded\"\nEnd Sub"; + + // Save the workbook as a macro‑enabled file + workbook.Save("AutomationModule.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/create-a-new-vba-module-with-utf8-code-page-and-add-multilingual-macro-text.cs b/macro-project/create-a-new-vba-module-with-utf8-code-page-and-add-multilingual-macro-text.cs new file mode 100644 index 0000000000..6ccdcc69ec --- /dev/null +++ b/macro-project/create-a-new-vba-module-with-utf8-code-page-and-add-multilingual-macro-text.cs @@ -0,0 +1,55 @@ +using System; +using System.Text; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class CreateVbaModuleWithMultilingualMacro +{ + public static void Run() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Set the VBA project encoding to UTF‑8 + vbaProject.Encoding = Encoding.UTF8; + + // Add a class module named "MultiLangModule" + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Class, "MultiLangModule"); + + // Retrieve the added module + VbaModule module = vbaProject.Modules[moduleIndex]; + + // Multilingual VBA macro (English, Chinese, Arabic) + string vbaCode = + "Sub ShowMessages()\r\n" + + " MsgBox \"Hello World!\" ' English\r\n" + + " MsgBox \"你好,世界!\" ' Chinese\r\n" + + " MsgBox \"مرحبا بالعالم!\" ' Arabic\r\n" + + "End Sub"; + + // Assign the code to the module + module.Codes = vbaCode; + + // Save the workbook as a macro‑enabled file + workbook.Save("MultilingualVbaModule.xlsm", SaveFormat.Xlsm); + } +} + +class Program +{ + static void Main() + { + try + { + CreateVbaModuleWithMultilingualMacro.Run(); + Console.WriteLine("Workbook created successfully."); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/create-a-new-xlsm-workbook-instance-and-add-a-vba-code-module.cs b/macro-project/create-a-new-xlsm-workbook-instance-and-add-a-vba-code-module.cs new file mode 100644 index 0000000000..45b0ed4c9e --- /dev/null +++ b/macro-project/create-a-new-xlsm-workbook-instance-and-add-a-vba-code-module.cs @@ -0,0 +1,29 @@ +using System; +using System.Text; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Create a new workbook instance + Workbook workbook = new Workbook(); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add a new procedural VBA module named "MyModule" + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Procedural, "MyModule"); + + // Retrieve the added module and assign VBA code to it + VbaModule module = vbaProject.Modules[moduleIndex]; + module.Codes = "Sub HelloWorld()\r\n MsgBox \"Hello from VBA!\"\r\nEnd Sub"; + + // Set the encoding for the VBA project (optional but recommended) + vbaProject.Encoding = Encoding.UTF8; + + // Save the workbook as a macro‑enabled file (XLSM) + workbook.Save("MyWorkbook.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/create-a-unit-test-that-verifies-macro-assignment-fails-when-the-macro-name-does-not-exist.cs b/macro-project/create-a-unit-test-that-verifies-macro-assignment-fails-when-the-macro-name-does-not-exist.cs new file mode 100644 index 0000000000..87f236c59a --- /dev/null +++ b/macro-project/create-a-unit-test-that-verifies-macro-assignment-fails-when-the-macro-name-does-not-exist.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Drawing; + +namespace ShapeMacroDemo +{ + class Program + { + static void Main() + { + try + { + AssignNonExistingMacro_ShouldFail(); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } + + // Test: assigning a macro that does not exist should cause an exception on save. + static void AssignNonExistingMacro_ShouldFail() + { + try + { + // Create a new workbook (lifecycle: create) + Workbook workbook = new Workbook(); + Worksheet worksheet = workbook.Worksheets[0]; + + // Add a rectangle shape to the worksheet + Shape shape = worksheet.Shapes.AddRectangle(1, 1, 100, 100, 0, 0); + + // Assign a non‑existing macro name + shape.MacroName = "NonExistingMacro()"; + + // Save the workbook to a memory stream (lifecycle: save) + using (MemoryStream ms = new MemoryStream()) + { + workbook.Save(ms, SaveFormat.Xlsm); + } + + // If we reach this point, no exception was thrown – the test failed. + Console.WriteLine("Test Failed: No exception was thrown when saving with a non‑existing macro."); + } + catch (Exception ex) + { + // Expected path: an exception should be thrown because the macro cannot be resolved. + Console.WriteLine($"Test Passed: Caught expected exception – {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/create-new-workbook-add-vba-module-with-code-then-digitally-sign-the-vba-project.cs b/macro-project/create-new-workbook-add-vba-module-with-code-then-digitally-sign-the-vba-project.cs new file mode 100644 index 0000000000..d53c1995ae --- /dev/null +++ b/macro-project/create-new-workbook-add-vba-module-with-code-then-digitally-sign-the-vba-project.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Text; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaSigningDemo +{ + class Program + { + static void Main() + { + try + { + // Create a new workbook (macro-enabled format will be used when saving) + Workbook workbook = new Workbook(); + + // Access the VBA project (it exists by default) + VbaProject vbaProject = workbook.VbaProject; + + // Set optional project properties + vbaProject.Name = "DemoVbaProject"; + vbaProject.Encoding = Encoding.UTF8; + + // Add a new class module to the VBA project + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Class, "DemoModule"); + VbaModule module = vbaProject.Modules[moduleIndex]; + + // Insert VBA code into the module + module.Codes = @"Sub HelloWorld() + MsgBox ""Hello from VBA!"" +End Sub"; + + // Load a digital certificate (replace with your actual .pfx path and password) + string certPath = "MyCertificate.pfx"; + string certPassword = "password"; + + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + X509Certificate2 certificate; + try + { + certificate = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.MachineKeySet); + } + catch (CryptographicException ex) + { + Console.WriteLine($"Failed to load certificate: {ex.Message}"); + return; + } + + // Create a DigitalSignature object + DigitalSignature digitalSignature = new DigitalSignature(certificate, "VBA Project Signature", DateTime.Now); + + // Sign the VBA project + try + { + vbaProject.Sign(digitalSignature); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to sign VBA project: {ex.Message}"); + return; + } + + // Save the workbook as a macro-enabled file + string outputPath = "SignedVbaWorkbook.xlsm"; + try + { + workbook.Save(outputPath, SaveFormat.Xlsm); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to save workbook: {ex.Message}"); + return; + } + + // Verify signing status + if (File.Exists(outputPath)) + { + Workbook verifyWorkbook = new Workbook(outputPath); + Console.WriteLine("VBA Project IsSigned: " + verifyWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + verifyWorkbook.VbaProject.IsValidSigned); + } + else + { + Console.WriteLine($"Failed to locate saved workbook: {outputPath}"); + } + } + catch (Exception ex) + { + // Catch any unexpected exceptions + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/create-x509certificate2-from-pfx-file-with-password-and-use-it-to-sign-vba-project.cs b/macro-project/create-x509certificate2-from-pfx-file-with-password-and-use-it-to-sign-vba-project.cs new file mode 100644 index 0000000000..0711e80ee6 --- /dev/null +++ b/macro-project/create-x509certificate2-from-pfx-file-with-password-and-use-it-to-sign-vba-project.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +class SignVbaProject +{ + static void Main() + { + try + { + // Verify input workbook exists + string inputFile = "input.xlsm"; + if (!File.Exists(inputFile)) + throw new FileNotFoundException($"Input file not found: {inputFile}"); + + // Load workbook containing VBA project + Workbook workbook = new Workbook(inputFile); + + // Access VBA project + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject != null) + { + // Verify certificate file exists + string certPath = "mycertificate.pfx"; + if (!File.Exists(certPath)) + throw new FileNotFoundException($"Certificate file not found: {certPath}"); + + // Load X509 certificate (replace password with the correct one) + string certPassword = "yourPassword"; + X509Certificate2 certificate; + try + { + certificate = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.MachineKeySet); + } + catch (CryptographicException ex) + { + Console.WriteLine($"Failed to load certificate: {ex.Message}"); + return; + } + + // Create digital signature + DigitalSignature signature = new DigitalSignature( + certificate, + "Signed by Aspose.Cells", + DateTime.Now); + + // Sign the VBA project + vbaProject.Sign(signature); + } + else + { + Console.WriteLine("The workbook does not contain a VBA project."); + } + + // Save signed workbook + string outputFile = "signed_output.xlsm"; + workbook.Save(outputFile, SaveFormat.Xlsm); + Console.WriteLine($"Signed workbook saved to: {outputFile}"); + } + catch (FileNotFoundException ex) + { + Console.WriteLine(ex.Message); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/delete-any-vba-module-that-exceeds-five-hundred-lines-of-code-after-enumerating-the-project-modules.cs b/macro-project/delete-any-vba-module-that-exceeds-five-hundred-lines-of-code-after-enumerating-the-project-modules.cs new file mode 100644 index 0000000000..ecc6cca51b --- /dev/null +++ b/macro-project/delete-any-vba-module-that-exceeds-five-hundred-lines-of-code-after-enumerating-the-project-modules.cs @@ -0,0 +1,40 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class DeleteLargeVbaModules +{ + static void Main() + { + // Load the macro-enabled workbook + Workbook workbook = new Workbook("input.xlsm"); + + // Access the VBA project and its modules + VbaProject vbaProject = workbook.VbaProject; + VbaModuleCollection modules = vbaProject.Modules; + + // Iterate backwards so removal does not affect the loop index + for (int i = modules.Count - 1; i >= 0; i--) + { + VbaModule module = modules[i]; + + // Determine the number of lines in the module's code + int lineCount = 0; + if (!string.IsNullOrEmpty(module.Codes)) + { + lineCount = module.Codes.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None).Length; + } + + // Remove modules that exceed 500 lines + if (lineCount > 500) + { + string name = module.Name; + modules.Remove(name); + Console.WriteLine($"Removed module '{name}' with {lineCount} lines."); + } + } + + // Save the workbook after removals + workbook.Save("output.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/detect-and-report-any-duplicate-macro-names-across-multiple-vba-modules-within-a-single-workbook.cs b/macro-project/detect-and-report-any-duplicate-macro-names-across-multiple-vba-modules-within-a-single-workbook.cs new file mode 100644 index 0000000000..8223c6af5a --- /dev/null +++ b/macro-project/detect-and-report-any-duplicate-macro-names-across-multiple-vba-modules-within-a-single-workbook.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroDuplicateDetector +{ + class Program + { + static void Main(string[] args) + { + // Path to the macro‑enabled workbook + string workbookPath = "sample_with_macro.xlsm"; + + // Verify that the workbook file exists before attempting to load it + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"File not found: {workbookPath}"); + return; + } + + try + { + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Ensure the workbook actually contains VBA macros + if (!workbook.HasMacro) + { + Console.WriteLine("The workbook does not contain any macros."); + return; + } + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + { + Console.WriteLine("No VBA project found in the workbook."); + return; + } + + // Map macro name → list of module names where it appears + var macroOccurrences = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + // Regex to capture Sub and Function definitions + var macroRegex = new Regex(@"\b(Sub|Function)\s+([A-Za-z_][A-Za-z0-9_]*)", + RegexOptions.IgnoreCase); + + // Scan each VBA module for macro definitions + foreach (VbaModule module in vbaProject.Modules) + { + string moduleName = module.Name; + string code = module.Codes ?? string.Empty; + + foreach (Match match in macroRegex.Matches(code)) + { + string macroName = match.Groups[2].Value; + + if (!macroOccurrences.ContainsKey(macroName)) + macroOccurrences[macroName] = new List(); + + macroOccurrences[macroName].Add(moduleName); + } + } + + // Report duplicate macro names + bool duplicatesFound = false; + foreach (var kvp in macroOccurrences) + { + if (kvp.Value.Count > 1) + { + duplicatesFound = true; + Console.WriteLine( + $"Duplicate macro name: '{kvp.Key}' found in modules: {string.Join(", ", kvp.Value)}"); + } + } + + if (!duplicatesFound) + Console.WriteLine("No duplicate macro names were found across the VBA modules."); + } + catch (Exception ex) + { + // Catch any runtime exceptions and display a friendly message + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/detect-unsigned-vba-projects-across-a-directory-and-list-file-names-for-further-review.cs b/macro-project/detect-unsigned-vba-projects-across-a-directory-and-list-file-names-for-further-review.cs new file mode 100644 index 0000000000..c7a89092bb --- /dev/null +++ b/macro-project/detect-unsigned-vba-projects-across-a-directory-and-list-file-names-for-further-review.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaAudit +{ + class Program + { + static void Main(string[] args) + { + // Directory to scan – change as needed + string folderPath = @"C:\ExcelFiles"; + + // Collect files with unsigned VBA projects + List unsignedVbaFiles = new List(); + + // Supported Excel extensions (including macro-enabled) + string[] extensions = new[] { ".xls", ".xlsx", ".xlsm", ".xlsb", ".xls2003", ".xls2007" }; + + foreach (string filePath in Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories)) + { + // Skip files that are not Excel based on extension + if (Array.IndexOf(extensions, Path.GetExtension(filePath).ToLower()) < 0) + continue; + + try + { + // Load the workbook (read‑only is sufficient for inspection) + Workbook workbook = new Workbook(filePath); + + // If the workbook contains VBA/macros + if (workbook.HasMacro) + { + // Check if the VBA project is signed + bool isSigned = workbook.VbaProject.IsSigned; + + // If not signed, add to the result list + if (!isSigned) + { + unsignedVbaFiles.Add(filePath); + } + } + } + catch (Exception ex) + { + // Log or ignore files that cannot be processed as Excel workbooks + Console.WriteLine($"Error processing '{filePath}': {ex.Message}"); + } + } + + // Output the list of files with unsigned VBA projects + Console.WriteLine("Files with unsigned VBA projects:"); + foreach (string file in unsignedVbaFiles) + { + Console.WriteLine(file); + } + } + } +} \ No newline at end of file diff --git a/macro-project/develop-a-console-application-that-accepts-a-folder-path-processes-each-xlsm-and-reports-macro-status.cs b/macro-project/develop-a-console-application-that-accepts-a-folder-path-processes-each-xlsm-and-reports-macro-status.cs new file mode 100644 index 0000000000..2a34106f43 --- /dev/null +++ b/macro-project/develop-a-console-application-that-accepts-a-folder-path-processes-each-xlsm-and-reports-macro-status.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace MacroStatusReporter +{ + class Program + { + static void Main(string[] args) + { + // Verify that a folder path was provided + if (args.Length == 0) + { + Console.WriteLine("Please provide a folder path as the first argument."); + return; + } + + string folderPath = args[0]; + + // Check if the folder exists + if (!Directory.Exists(folderPath)) + { + Console.WriteLine($"The folder \"{folderPath}\" does not exist."); + return; + } + + // Get all .xlsm files in the folder (non‑recursive) + string[] xlsmFiles = Directory.GetFiles(folderPath, "*.xlsm", SearchOption.TopDirectoryOnly); + + if (xlsmFiles.Length == 0) + { + Console.WriteLine("No macro‑enabled Excel files (*.xlsm) were found in the specified folder."); + return; + } + + Console.WriteLine($"Processing {xlsmFiles.Length} file(s) in \"{folderPath}\":"); + + foreach (string filePath in xlsmFiles) + { + try + { + // Load the workbook (uses the Workbook(string) constructor rule) + Workbook workbook = new Workbook(filePath); + + // Check if the workbook contains macros (uses the HasMacro property rule) + bool hasMacro = workbook.HasMacro; + + // Report the result + Console.WriteLine($"{Path.GetFileName(filePath)} : HasMacro = {hasMacro}"); + } + catch (Exception ex) + { + // Report any errors encountered while processing the file + Console.WriteLine($"{Path.GetFileName(filePath)} : Error - {ex.Message}"); + } + } + } + } +} \ No newline at end of file diff --git a/macro-project/embed-vba-code-that-disables-the-print-command-into-a-workbook-to-prevent-user-printing.cs b/macro-project/embed-vba-code-that-disables-the-print-command-into-a-workbook-to-prevent-user-printing.cs new file mode 100644 index 0000000000..815adc8a6a --- /dev/null +++ b/macro-project/embed-vba-code-that-disables-the-print-command-into-a-workbook-to-prevent-user-printing.cs @@ -0,0 +1,47 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaPrintDisableDemo +{ + class Program + { + static void Main() + { + try + { + // Create a new empty workbook + Workbook workbook = new Workbook(); + + // The workbook already contains a class module named "ThisWorkbook" + // Retrieve that existing module instead of adding a duplicate + VbaModule thisWorkbookModule = workbook.VbaProject.Modules["ThisWorkbook"]; + + // VBA code that cancels any print attempt + // The Workbook_BeforePrint event is triggered before printing; setting Cancel = True stops the print + string vbaCode = + "Private Sub Workbook_BeforePrint(Cancel As Boolean)\r\n" + + " Cancel = True\r\n" + + " MsgBox \"Printing is disabled for this workbook.\"\r\n" + + "End Sub"; + + // Assign the VBA code to the module + thisWorkbookModule.Codes = vbaCode; + + // (Optional) Protect the VBA project to prevent users from viewing/modifying the code + // Here we protect without locking for viewing, using a password + workbook.VbaProject.Protect(false, "vbaPassword123"); + + // Save the workbook as a macro‑enabled file (.xlsm) so the VBA code is retained + string outputPath = "WorkbookWithPrintDisabled.xlsm"; + workbook.Save(outputPath, SaveFormat.Xlsm); + + Console.WriteLine($"Workbook saved to '{outputPath}'. Printing is now disabled via VBA."); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/enumerate-all-modules-in-the-vbaproject-and-output-each-module-name-to-the-console.cs b/macro-project/enumerate-all-modules-in-the-vbaproject-and-output-each-module-name-to-the-console.cs new file mode 100644 index 0000000000..393af4685a --- /dev/null +++ b/macro-project/enumerate-all-modules-in-the-vbaproject-and-output-each-module-name-to-the-console.cs @@ -0,0 +1,34 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Create a new workbook (macro-enabled) + Workbook workbook = new Workbook(); + + // Access the VBA project of the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add sample modules (optional, just to ensure there are modules to enumerate) + int idx1 = vbaProject.Modules.Add(VbaModuleType.Procedural, "Module1"); + vbaProject.Modules[idx1].Codes = "Sub Macro1()\nEnd Sub"; + + int idx2 = vbaProject.Modules.Add(VbaModuleType.Class, "ClassModule"); + vbaProject.Modules[idx2].Codes = "Public Sub ClassMethod()\nEnd Sub"; + + // Get the collection of modules + VbaModuleCollection modules = vbaProject.Modules; + + // Enumerate all modules and output each module name to the console + for (int i = 0; i < modules.Count; i++) + { + Console.WriteLine(modules[i].Name); + } + + // Save the workbook as a macro-enabled file (optional) + workbook.Save("EnumeratedModules.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/export-a-vba-certificate-to-a-temporary-file-then-load-it-into-an-x509certificate-object-for-inspection.cs b/macro-project/export-a-vba-certificate-to-a-temporary-file-then-load-it-into-an-x509certificate-object-for-inspection.cs new file mode 100644 index 0000000000..8e7e4449f1 --- /dev/null +++ b/macro-project/export-a-vba-certificate-to-a-temporary-file-then-load-it-into-an-x509certificate-object-for-inspection.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class VbaCertificateExportDemo + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } + + public static void Run() + { + // Path to an existing workbook that contains a signed VBA project + string signedWorkbookPath = "SignedWithVba.xlsm"; + + // Verify the workbook file exists + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"Workbook file not found: {signedWorkbookPath}"); + return; + } + + // Load the workbook + Workbook workbook; + try + { + workbook = new Workbook(signedWorkbookPath); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load workbook: {ex.Message}"); + return; + } + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Ensure the VBA project is signed + if (!vbaProject.IsSigned) + { + Console.WriteLine("The VBA project is not signed. No certificate to export."); + return; + } + + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + if (certData == null || certData.Length == 0) + { + Console.WriteLine("Certificate raw data is empty."); + return; + } + + // Load the certificate directly from the raw data (no temporary file needed) + X509Certificate2 certificate; + try + { + certificate = new X509Certificate2(certData); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load certificate from raw data: {ex.Message}"); + return; + } + + // Display some certificate information + Console.WriteLine($"Certificate Subject: {certificate.Subject}"); + Console.WriteLine($"Certificate Issuer: {certificate.Issuer}"); + Console.WriteLine($"Certificate Thumbprint: {certificate.Thumbprint}"); + Console.WriteLine($"Valid From: {certificate.NotBefore}"); + Console.WriteLine($"Valid To: {certificate.NotAfter}"); + } + } +} \ No newline at end of file diff --git a/macro-project/export-certificate-to-byte-array-then-write-bytes-to-file-for-external-distribution.cs b/macro-project/export-certificate-to-byte-array-then-write-bytes-to-file-for-external-distribution.cs new file mode 100644 index 0000000000..0f22b6b650 --- /dev/null +++ b/macro-project/export-certificate-to-byte-array-then-write-bytes-to-file-for-external-distribution.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class ExportVbaCertificateDemo + { + public static void Run() + { + try + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Verify the workbook file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project exists and is signed + if (vbaProject != null && vbaProject.IsSigned) + { + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + // Ensure we have data before writing to file + if (certData != null && certData.Length > 0) + { + string outputFile = "VbaCertificate.cer"; + + // Write the certificate bytes to a file + File.WriteAllBytes(outputFile, certData); + + Console.WriteLine($"Certificate exported successfully to '{outputFile}'. Length: {certData.Length} bytes."); + } + else + { + Console.WriteLine("Certificate data is empty."); + } + } + else + { + Console.WriteLine("VBA project is not signed or not present."); + } + + // Save the workbook + workbook.Save("ExportDemo.xlsx"); + Console.WriteLine("Workbook saved as 'ExportDemo.xlsx'."); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + + // Entry point for the application + public static void Main(string[] args) + { + Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/export-certificates-from-workbooks-using-asynchronous-tasks-to-improve-performance-on-large-file-sets.cs b/macro-project/export-certificates-from-workbooks-using-asynchronous-tasks-to-improve-performance-on-large-file-sets.cs new file mode 100644 index 0000000000..2f58fc05e9 --- /dev/null +++ b/macro-project/export-certificates-from-workbooks-using-asynchronous-tasks-to-improve-performance-on-large-file-sets.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Aspose.Cells; + +namespace AsposeCellsAsyncExport +{ + public class CertificateExporter + { + /// + /// Exports the first XML map (treated as a certificate) from each workbook asynchronously. + /// + /// Full paths of the workbooks to process. + /// Directory where the exported XML files will be saved. + /// A task that represents the asynchronous operation. + public static async Task ExportCertificatesAsync(string[] workbookPaths, string outputDirectory) + { + // Ensure the output directory exists. + Directory.CreateDirectory(outputDirectory); + + var exportTasks = new List(); + + foreach (string wbPath in workbookPaths) + { + // Capture the current path for the lambda. + string currentPath = wbPath; + + // Create a task for each workbook. + Task exportTask = Task.Run(() => + { + try + { + // Verify the workbook file exists before loading. + if (!File.Exists(currentPath)) + { + Console.WriteLine($"File not found: {currentPath}"); + return; + } + + // Load the workbook. + using (var workbook = new Workbook(currentPath)) + { + // Check if there is at least one XmlMap. + if (workbook.Worksheets.XmlMaps.Count > 0) + { + // Get the first XmlMap. + XmlMap xmlMap = workbook.Worksheets.XmlMaps[0]; + + // Build the output XML file name. + string xmlFileName = Path.GetFileNameWithoutExtension(currentPath) + "_" + xmlMap.Name + ".xml"; + string xmlFullPath = Path.Combine(outputDirectory, xmlFileName); + + // Export the XML data. + workbook.ExportXml(xmlMap.Name, xmlFullPath); + } + else + { + Console.WriteLine($"No XmlMap found in workbook: {currentPath}"); + } + } + } + catch (Exception ex) + { + // Log any unexpected errors for this workbook. + Console.WriteLine($"Error processing '{currentPath}': {ex.Message}"); + } + }); + + exportTasks.Add(exportTask); + } + + // Await all export tasks to complete. + await Task.WhenAll(exportTasks); + } + + // Example usage. + public static async Task RunExample() + { + // Example list of workbook files. + string[] workbooks = new string[] + { + @"C:\Data\Workbook1.xlsx", + @"C:\Data\Workbook2.xlsx", + @"C:\Data\Workbook3.xlsx" + }; + + // Destination folder for exported XML certificates. + string outputDir = @"C:\Data\ExportedCertificates"; + + // Perform asynchronous export. + await ExportCertificatesAsync(workbooks, outputDir); + + Console.WriteLine("All certificates have been exported."); + } + } + + // Entry point for demonstration. + class Program + { + static async Task Main(string[] args) + { + await CertificateExporter.RunExample(); + } + } +} \ No newline at end of file diff --git a/macro-project/export-each-workbooks-vba-module-code-to-separate-bas-files-for-version-control-tracking.cs b/macro-project/export-each-workbooks-vba-module-code-to-separate-bas-files-for-version-control-tracking.cs new file mode 100644 index 0000000000..734a7743ce --- /dev/null +++ b/macro-project/export-each-workbooks-vba-module-code-to-separate-bas-files-for-version-control-tracking.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaExport +{ + public class VbaExporter + { + // Exports VBA modules from all macro-enabled workbooks in a folder to .bas files. + public static void Run(string inputFolder, string outputFolder) + { + // Ensure the output directory exists. + Directory.CreateDirectory(outputFolder); + + // Get all Excel macro-enabled files (*.xlsm) in the input folder. + string[] workbookFiles = Directory.GetFiles(inputFolder, "*.xlsm", SearchOption.TopDirectoryOnly); + + foreach (string workbookPath in workbookFiles) + { + // Verify the workbook file still exists. + if (!File.Exists(workbookPath)) + { + continue; + } + + try + { + // Load the workbook (lifecycle rule: load). + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project; it may be null if the workbook has no macros. + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + { + // No VBA project present; skip this workbook. + continue; + } + + // Iterate through all VBA modules in the project. + for (int i = 0; i < vbaProject.Modules.Count; i++) + { + VbaModule module = vbaProject.Modules[i]; + + // Retrieve the VBA source code from the module. + string code = module.Codes ?? string.Empty; + + // Construct a file name: _.bas + string workbookName = Path.GetFileNameWithoutExtension(workbookPath); + string safeModuleName = MakeFileSystemSafe(module.Name); + string basFileName = $"{workbookName}_{safeModuleName}.bas"; + + // Full path for the .bas file. + string basFilePath = Path.Combine(outputFolder, basFileName); + + // Write the code to the .bas file (lifecycle rule: save). + File.WriteAllText(basFilePath, code); + } + } + catch (Exception ex) + { + // Log and continue with next workbook. + Console.Error.WriteLine($"Error processing '{workbookPath}': {ex.Message}"); + } + } + } + + // Helper to replace invalid filename characters. + private static string MakeFileSystemSafe(string name) + { + foreach (char c in Path.GetInvalidFileNameChars()) + { + name = name.Replace(c, '_'); + } + return name; + } + } + + // Entry point for the console application. + public static class Program + { + public static void Main(string[] args) + { + try + { + if (args.Length < 2) + { + Console.WriteLine("Usage: AsposeCellsVbaExport "); + return; + } + + string inputFolder = args[0]; + string outputFolder = args[1]; + + if (!Directory.Exists(inputFolder)) + { + Console.Error.WriteLine($"Input folder does not exist: {inputFolder}"); + return; + } + + VbaExporter.Run(inputFolder, outputFolder); + Console.WriteLine("VBA export completed successfully."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unhandled exception: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-certificate-to-a-base64-string-for-inclusion-in-configuration.cs b/macro-project/export-the-vba-projects-certificate-to-a-base64-string-for-inclusion-in-configuration.cs new file mode 100644 index 0000000000..3202ddb170 --- /dev/null +++ b/macro-project/export-the-vba-projects-certificate-to-a-base64-string-for-inclusion-in-configuration.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsDemo +{ + class ExportVbaCertificate + { + public static void Run() + { + try + { + // Path to the input workbook + string inputPath = "SignedWorkbook.xlsm"; + + // Verify that the input file exists + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input file not found: {inputPath}"); + return; + } + + // Load the workbook that contains a signed VBA project + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is signed and certificate data exists + if (vbaProject.IsSigned && vbaProject.CertRawData != null && vbaProject.CertRawData.Length > 0) + { + // Convert the raw certificate bytes to a Base64 string + string base64Certificate = Convert.ToBase64String(vbaProject.CertRawData); + + // Output the Base64 string (could be stored in a configuration file) + Console.WriteLine("Base64 encoded VBA certificate:"); + Console.WriteLine(base64Certificate); + + // Write the Base64 string to a config file + File.WriteAllText("VbaCertificate.config", base64Certificate); + } + else + { + Console.WriteLine("The VBA project is not signed or certificate data is unavailable."); + } + + // Save the workbook (no modifications made, but follows lifecycle rule) + workbook.Save("SignedWorkbook_Processed.xlsm", SaveFormat.Xlsm); + } + catch (Exception ex) + { + // Log any unexpected errors + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + class Program + { + static void Main(string[] args) + { + ExportVbaCertificate.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-certificate-to-a-cer-file-and-verify-its-thumbprint.cs b/macro-project/export-the-vba-projects-certificate-to-a-cer-file-and-verify-its-thumbprint.cs new file mode 100644 index 0000000000..9947ad8d2a --- /dev/null +++ b/macro-project/export-the-vba-projects-certificate-to-a-cer-file-and-verify-its-thumbprint.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaCertificateExport +{ + class Program + { + static void Main() + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Load the workbook (lifecycle rule: load) + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Check if the VBA project is signed + if (vbaProject.IsSigned) + { + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + if (certData != null && certData.Length > 0) + { + // Export the certificate to a .cer file (lifecycle rule: save) + string certFilePath = "VbaProjectCertificate.cer"; + File.WriteAllBytes(certFilePath, certData); + Console.WriteLine($"Certificate exported to: {certFilePath}"); + + // Load the certificate from the raw data + X509Certificate2 certificate = new X509Certificate2(certData); + + // Display the thumbprint of the certificate + Console.WriteLine($"Certificate Thumbprint: {certificate.Thumbprint}"); + } + else + { + Console.WriteLine("Certificate data is empty."); + } + } + else + { + Console.WriteLine("The VBA project is not signed; no certificate to export."); + } + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-certificate-to-a-file-path-and-verify-the-file-exists.cs b/macro-project/export-the-vba-projects-certificate-to-a-file-path-and-verify-the-file-exists.cs new file mode 100644 index 0000000000..bd6cedb95c --- /dev/null +++ b/macro-project/export-the-vba-projects-certificate-to-a-file-path-and-verify-the-file-exists.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class ExportVbaCertificateDemo + { + public static void Run() + { + try + { + // Path to the signed workbook containing a VBA project + string signedWorkbookPath = "SignedWorkbook.xlsm"; + + // Ensure the workbook file exists before attempting to load it + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"Workbook not found: {signedWorkbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(signedWorkbookPath); + + // Access the VBA project within the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is signed + if (!vbaProject.IsSigned) + { + Console.WriteLine("VBA project is not signed. No certificate to export."); + return; + } + + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + if (certData == null || certData.Length == 0) + { + Console.WriteLine("Certificate data is empty."); + return; + } + + // Define the output file path for the exported certificate + string certFilePath = "VbaProjectCertificate.cer"; + + // Write the certificate bytes to the file + File.WriteAllBytes(certFilePath, certData); + Console.WriteLine($"Certificate exported to: {certFilePath}"); + + // Verify that the file was created successfully + bool fileExists = File.Exists(certFilePath); + Console.WriteLine($"Verification - file exists: {fileExists}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + // Entry point for the application + public class Program + { + public static void Main(string[] args) + { + try + { + ExportVbaCertificateDemo.Run(); + } + catch (Exception ex) + { + Console.WriteLine($"Unhandled exception: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-certificate-to-a-memorystream-and-write-stream-contents-to-disk.cs b/macro-project/export-the-vba-projects-certificate-to-a-memorystream-and-write-stream-contents-to-disk.cs new file mode 100644 index 0000000000..9268d764e2 --- /dev/null +++ b/macro-project/export-the-vba-projects-certificate-to-a-memorystream-and-write-stream-contents-to-disk.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsDemo +{ + class ExportVbaCertificate + { + public static void Run() + { + try + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Verify that the workbook file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Error: Workbook file not found at '{workbookPath}'."); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Ensure the project is signed and certificate data exists + if (vbaProject != null && vbaProject.IsSigned) + { + byte[] certData = vbaProject.CertRawData; + + if (certData != null && certData.Length > 0) + { + // Export the certificate raw data to a file + string outputPath = "VbaCertificate.cer"; + + // Write the certificate bytes to disk + using (FileStream fileStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) + { + fileStream.Write(certData, 0, certData.Length); + } + + Console.WriteLine($"Certificate exported successfully to '{outputPath}'."); + } + else + { + Console.WriteLine("No certificate data found in the VBA project."); + } + } + else + { + Console.WriteLine("The workbook does not contain a signed VBA project."); + } + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + class Program + { + static void Main(string[] args) + { + ExportVbaCertificate.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-certificate-to-a-pfx-file-protected-by-a-password-for-secure-storage.cs b/macro-project/export-the-vba-projects-certificate-to-a-pfx-file-protected-by-a-password-for-secure-storage.cs new file mode 100644 index 0000000000..5e3f9a1265 --- /dev/null +++ b/macro-project/export-the-vba-projects-certificate-to-a-pfx-file-protected-by-a-password-for-secure-storage.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class ExportVbaCertificate + { + public static void Run() + { + try + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Verify that the workbook file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file '{workbookPath}' not found."); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is signed and certificate data is available + if (vbaProject.IsSigned && vbaProject.CertRawData != null && vbaProject.CertRawData.Length > 0) + { + // Retrieve the raw certificate bytes + byte[] certData = vbaProject.CertRawData; + + // Create an X509Certificate2 instance from the raw data + X509Certificate2 certificate = new X509Certificate2(certData); + + // Define a password to protect the exported PFX file + string pfxPassword = "StrongPassword123"; + + // Export the certificate to a PFX (PKCS#12) byte array, protected by the password + byte[] pfxBytes = certificate.Export(X509ContentType.Pfx, pfxPassword); + + // Save the PFX file to disk + string pfxPath = "VbaProjectCertificate.pfx"; + File.WriteAllBytes(pfxPath, pfxBytes); + + Console.WriteLine($"Certificate exported successfully to '{pfxPath}'."); + } + else + { + Console.WriteLine("The VBA project is not signed or does not contain certificate data."); + } + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } + + public class Program + { + public static void Main(string[] args) + { + ExportVbaCertificate.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-digital-certificate-to-a-file-path.cs b/macro-project/export-the-vba-projects-digital-certificate-to-a-file-path.cs new file mode 100644 index 0000000000..bcb263ac0d --- /dev/null +++ b/macro-project/export-the-vba-projects-digital-certificate-to-a-file-path.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +public class ExportVbaCertificate +{ + // Entry point for the console application. + public static void Main(string[] args) + { + // Expect two arguments: workbook path and certificate output path. + if (args.Length < 2) + { + Console.WriteLine("Usage: ExportVbaCertificate "); + return; + } + + string workbookPath = args[0]; + string certificateFilePath = args[1]; + + Run(workbookPath, certificateFilePath); + } + + // Exports the VBA project's digital certificate to the specified file path. + public static void Run(string workbookPath, string certificateFilePath) + { + try + { + // Verify that the workbook file exists before loading. + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Load the workbook that contains the VBA project. + Workbook workbook = new Workbook(workbookPath); + + // Get the VBA project from the workbook. + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is signed. + if (vbaProject.IsSigned) + { + // Retrieve the raw certificate data. + byte[] certData = vbaProject.CertRawData; + + // Ensure the certificate data is present. + if (certData != null && certData.Length > 0) + { + // Write the certificate data to the specified file. + File.WriteAllBytes(certificateFilePath, certData); + Console.WriteLine($"Certificate exported successfully to: {certificateFilePath}"); + } + else + { + Console.WriteLine("Certificate data is empty; nothing was exported."); + } + } + else + { + Console.WriteLine("The VBA project is not signed; no certificate to export."); + } + } + catch (Exception ex) + { + // Catch any unexpected errors and display a friendly message. + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-digital-certificate-to-a-memorystream-for-further-processing.cs b/macro-project/export-the-vba-projects-digital-certificate-to-a-memorystream-for-further-processing.cs new file mode 100644 index 0000000000..a39f8ab7ab --- /dev/null +++ b/macro-project/export-the-vba-projects-digital-certificate-to-a-memorystream-for-further-processing.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +public class ExportVbaCertificateDemo +{ + // Exports the VBA project's digital certificate to a MemoryStream. + public static MemoryStream ExportCertificate(string workbookPath) + { + // Ensure the workbook file exists. + if (!File.Exists(workbookPath)) + throw new FileNotFoundException($"Workbook file not found: {workbookPath}"); + + Workbook workbook; + try + { + // Load the workbook that contains the signed VBA project. + workbook = new Workbook(workbookPath); + } + catch (Exception ex) + { + throw new InvalidOperationException("Failed to load workbook.", ex); + } + + // Access the VBA project. + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + throw new InvalidOperationException("Workbook does not contain a VBA project."); + + // Verify that the VBA project is signed. + if (!vbaProject.IsSigned) + throw new InvalidOperationException("The VBA project is not signed."); + + // Retrieve the raw certificate data. + byte[] certData = vbaProject.CertRawData; + if (certData == null || certData.Length == 0) + throw new InvalidOperationException("Certificate raw data is unavailable."); + + // Write the certificate data into a MemoryStream. + return new MemoryStream(certData); + } + + // Demonstrates usage of the ExportCertificate method. + public static void Run() + { + string signedWorkbookPath = "SignedWorkbook.xlsm"; + + try + { + // Export the certificate to a memory stream. + using (MemoryStream certificateStream = ExportCertificate(signedWorkbookPath)) + { + Console.WriteLine($"Certificate exported successfully. Length: {certificateStream.Length}"); + // Further processing of the certificateStream can be performed here. + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + + // Entry point for the application. + public static void Main(string[] args) + { + try + { + Run(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unhandled exception: {ex}"); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vba-projects-digital-certificate-to-a-pem-file-for-backup.cs b/macro-project/export-the-vba-projects-digital-certificate-to-a-pem-file-for-backup.cs new file mode 100644 index 0000000000..03537dd462 --- /dev/null +++ b/macro-project/export-the-vba-projects-digital-certificate-to-a-pem-file-for-backup.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ExportVbaCertificate +{ + static void Main() + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Destination path for the exported PEM file + string pemFilePath = "VbaCertificate.pem"; + + // Load the workbook (uses Aspose.Cells lifecycle rule) + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Verify that the VBA project is signed and certificate data is present + if (vbaProject.IsSigned && vbaProject.CertRawData != null && vbaProject.CertRawData.Length > 0) + { + // Create an X509Certificate2 instance from the raw certificate bytes + X509Certificate2 certificate = new X509Certificate2(vbaProject.CertRawData); + + // Export the certificate to DER format and then encode it as Base64 with line breaks + string base64Cert = Convert.ToBase64String( + certificate.Export(X509ContentType.Cert), + Base64FormattingOptions.InsertLineBreaks); + + // Build the PEM representation + string pemContent = "-----BEGIN CERTIFICATE-----\n" + + base64Cert + + "\n-----END CERTIFICATE-----"; + + // Write the PEM content to the specified file + File.WriteAllText(pemFilePath, pemContent); + + Console.WriteLine($"Certificate exported successfully to: {pemFilePath}"); + } + else + { + Console.WriteLine("The VBA project is not signed or certificate data is unavailable."); + } + } +} \ No newline at end of file diff --git a/macro-project/export-the-vbaprojects-digital-certificate-to-a-file-stream-for-external-backup-purposes.cs b/macro-project/export-the-vbaprojects-digital-certificate-to-a-file-stream-for-external-backup-purposes.cs new file mode 100644 index 0000000000..93760a3ec8 --- /dev/null +++ b/macro-project/export-the-vbaprojects-digital-certificate-to-a-file-stream-for-external-backup-purposes.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +public class ExportVbaCertificate +{ + public static void Run() + { + try + { + // Path to the workbook that contains a signed VBA project + string workbookPath = "SignedWorkbook.xlsm"; + + // Verify that the workbook file exists to avoid FileNotFoundException + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Check if the VBA project is signed + if (vbaProject != null && vbaProject.IsSigned) + { + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + if (certData != null && certData.Length > 0) + { + // Export the certificate to an in‑memory stream and then to a file + using (MemoryStream memoryStream = new MemoryStream()) + { + memoryStream.Write(certData, 0, certData.Length); + memoryStream.Position = 0; // Reset for reading + + // Write the stream to a file for external backup + using (FileStream fileStream = new FileStream("VbaCertificateBackup.cer", FileMode.Create, FileAccess.Write)) + { + memoryStream.CopyTo(fileStream); + } + } + + Console.WriteLine("VBA certificate exported successfully."); + } + else + { + Console.WriteLine("Certificate data is empty."); + } + } + else + { + Console.WriteLine("VBA project is not signed; no certificate to export."); + } + } + catch (Exception ex) + { + // Log any unexpected errors + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } +} + +// Entry point for the application +public class Program +{ + public static void Main(string[] args) + { + ExportVbaCertificate.Run(); + } +} \ No newline at end of file diff --git a/macro-project/generate-a-csv-file-containing-workbook-names-macro-assignment-status-and-signature-verification-results.cs b/macro-project/generate-a-csv-file-containing-workbook-names-macro-assignment-status-and-signature-verification-results.cs new file mode 100644 index 0000000000..4a84f1ad9d --- /dev/null +++ b/macro-project/generate-a-csv-file-containing-workbook-names-macro-assignment-status-and-signature-verification-results.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Aspose.Cells; + +class Program +{ + static void Main() + { + // Folder that contains the Excel workbooks to be inspected + string inputFolder = "InputWorkbooks"; + + // Path of the CSV file that will hold the report + string csvPath = "WorkbookReport.csv"; + + // Retrieve all files in the folder and filter for Excel extensions + string[] allFiles = Directory.GetFiles(inputFolder, "*.*", SearchOption.TopDirectoryOnly); + string[] excelFiles = Array.FindAll(allFiles, f => + f.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase) || + f.EndsWith(".xlsm", StringComparison.OrdinalIgnoreCase) || + f.EndsWith(".xls", StringComparison.OrdinalIgnoreCase)); + + // Create the CSV and write the header + using (StreamWriter writer = new StreamWriter(csvPath)) + { + writer.WriteLine("WorkbookName,HasMacro,IsDigitallySigned"); + + // Process each workbook + foreach (string filePath in excelFiles) + { + // Load the workbook using the provided constructor rule + Workbook workbook = new Workbook(filePath); + + // Gather required properties + bool hasMacro = workbook.HasMacro; // macro assignment status + bool isSigned = workbook.IsDigitallySigned; // digital signature verification + + // Write a CSV line for the current workbook + string line = $"{Path.GetFileName(filePath)},{hasMacro},{isSigned}"; + writer.WriteLine(line); + + // Release resources + workbook.Dispose(); + } + } + + // The CSV file "WorkbookReport.csv" now contains the desired information. + } +} \ No newline at end of file diff --git a/macro-project/generate-a-summary-of-all-vba-modules-including-line-counts-and-write-the-report-to-a-text-file.cs b/macro-project/generate-a-summary-of-all-vba-modules-including-line-counts-and-write-the-report-to-a-text-file.cs new file mode 100644 index 0000000000..f6cec5d31a --- /dev/null +++ b/macro-project/generate-a-summary-of-all-vba-modules-including-line-counts-and-write-the-report-to-a-text-file.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaSummary +{ + class Program + { + static void Main(string[] args) + { + // Input Excel file (must be a macro‑enabled workbook, e.g., .xlsm) + string inputPath = "input.xlsm"; + + // Output text file that will contain the summary + string reportPath = "VbaModulesReport.txt"; + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project; if none exists, exit + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Get the collection of VBA modules + VbaModuleCollection modules = vbaProject.Modules; + + // Prepare to write the report + using (StreamWriter writer = new StreamWriter(reportPath)) + { + writer.WriteLine($"VBA Modules Summary for '{Path.GetFileName(inputPath)}'"); + writer.WriteLine(new string('=', 50)); + + // Iterate through each module + for (int i = 0; i < modules.Count; i++) + { + VbaModule module = modules[i]; + string code = module.Codes ?? string.Empty; + + // Count non‑empty lines in the module code + int lineCount = 0; + if (!string.IsNullOrEmpty(code)) + { + // Split on both CR and LF to handle different line endings + string[] lines = code.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + lineCount = lines.Length; + } + + // Write module details to the report + writer.WriteLine($"Module {i + 1}:"); + writer.WriteLine($" Name : {module.Name}"); + writer.WriteLine($" Type : {module.Type}"); + writer.WriteLine($" Line Count: {lineCount}"); + writer.WriteLine(); + } + + writer.WriteLine("End of Summary"); + } + + Console.WriteLine($"VBA modules summary written to '{reportPath}'."); + } + } +} \ No newline at end of file diff --git a/macro-project/generate-report-listing-signed-versus-unsigned-workbooks-in-specified-directory-for-compliance-review.cs b/macro-project/generate-report-listing-signed-versus-unsigned-workbooks-in-specified-directory-for-compliance-review.cs new file mode 100644 index 0000000000..ee7944dc81 --- /dev/null +++ b/macro-project/generate-report-listing-signed-versus-unsigned-workbooks-in-specified-directory-for-compliance-review.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Aspose.Cells; + +namespace ComplianceReport +{ + class Program + { + static void Main(string[] args) + { + try + { + // Directory containing the workbooks to scan + string sourceDirectory = @"C:\Workbooks"; // TODO: change to your directory + + // Output report file path + string reportPath = @"C:\ComplianceReport\SignedStatusReport.xlsx"; + + // Collect workbook file paths (common Excel extensions) + List workbookFiles = new List(); + string[] extensions = new[] { "*.xlsx", "*.xls", "*.xlsm", "*.xlsb", "*.xlsxml", "*.ods" }; + if (Directory.Exists(sourceDirectory)) + { + foreach (string ext in extensions) + { + workbookFiles.AddRange(Directory.GetFiles(sourceDirectory, ext, SearchOption.AllDirectories)); + } + } + + // Prepare data for the report + List<(string FilePath, bool IsSigned)> results = new List<(string, bool)>(); + foreach (string file in workbookFiles) + { + // Ensure the file exists before attempting to load + if (!File.Exists(file)) + continue; + + bool signed = false; + try + { + // Load the workbook + using (Workbook wb = new Workbook(file)) + { + // Check digital signature status + signed = wb.IsDigitallySigned; + } + } + catch (CellsException) + { + // Password‑protected or otherwise unreadable files are treated as not signed + signed = false; + } + catch (Exception) + { + // Any other loading issue – skip this file + continue; + } + + results.Add((file, signed)); + } + + // Create a new workbook for the report + using (Workbook reportWorkbook = new Workbook()) + { + Worksheet sheet = reportWorkbook.Worksheets[0]; + + // Write header + sheet.Cells["A1"].PutValue("File Path"); + sheet.Cells["B1"].PutValue("Digitally Signed"); + + // Write data rows + int rowIndex = 1; // zero‑based index; row 1 is the second row (after header) + foreach (var item in results) + { + sheet.Cells[rowIndex, 0].PutValue(item.FilePath); + sheet.Cells[rowIndex, 1].PutValue(item.IsSigned); + rowIndex++; + } + + // Ensure the output directory exists + string? reportDir = Path.GetDirectoryName(reportPath); + if (!string.IsNullOrEmpty(reportDir) && !Directory.Exists(reportDir)) + { + Directory.CreateDirectory(reportDir); + } + + // Save the report workbook + reportWorkbook.Save(reportPath, SaveFormat.Xlsx); + } + + Console.WriteLine($"Compliance report generated at: {reportPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/if-the-project-is-unprotected-apply-password-protection-with-the-protect-method-and-a-strong-password.cs b/macro-project/if-the-project-is-unprotected-apply-password-protection-with-the-protect-method-and-a-strong-password.cs new file mode 100644 index 0000000000..4ff31918b0 --- /dev/null +++ b/macro-project/if-the-project-is-unprotected-apply-password-protection-with-the-protect-method-and-a-strong-password.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; // Required for VbaProject class + +namespace AsposeCellsExamples +{ + public class ProtectVbaProjectIfUnprotected + { + public static void Run() + { + // Paths for input and output workbooks + string inputPath = "input.xlsm"; + string outputPath = "output_protected.xlsm"; + + try + { + // Verify that the input file exists to avoid FileNotFoundException + if (!File.Exists(inputPath)) + throw new FileNotFoundException($"Input file not found: {inputPath}"); + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project (may be null if workbook has no VBA) + VbaProject vbaProject = workbook.VbaProject; + + // Protect the VBA project if it exists and is not already protected + if (vbaProject != null && !vbaProject.IsProtected) + { + // Protect the VBA project with a password (not locked for viewing) + vbaProject.Protect(false, "Str0ngP@ssw0rd!2026"); + } + + // Save the protected workbook + workbook.Save(outputPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved successfully to '{outputPath}'."); + } + catch (Exception ex) + { + // Log any errors that occur during processing + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + } + + // Entry point required for console applications + public class Program + { + public static void Main(string[] args) + { + ProtectVbaProjectIfUnprotected.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/implement-a-function-that-checks-whether-a-workbook-contains-any-form-controls-before-assigning-macros.cs b/macro-project/implement-a-function-that-checks-whether-a-workbook-contains-any-form-controls-before-assigning-macros.cs new file mode 100644 index 0000000000..3b12aa836b --- /dev/null +++ b/macro-project/implement-a-function-that-checks-whether-a-workbook-contains-any-form-controls-before-assigning-macros.cs @@ -0,0 +1,75 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; + +namespace AsposeCellsFormControlCheck +{ + public class MacroHelper + { + // Checks if the workbook contains any form controls (CheckBoxes or ActiveX controls) + public static bool ContainsFormControls(Workbook workbook) + { + // Iterate through all worksheets in the workbook + foreach (Worksheet sheet in workbook.Worksheets) + { + // Check for legacy form controls (CheckBox collection) + if (sheet.CheckBoxes.Count > 0) + { + return true; + } + + // Check for ActiveX controls embedded as shapes + foreach (Shape shape in sheet.Shapes) + { + if (shape.ActiveXControl != null) + { + return true; + } + } + } + + // No form controls found + return false; + } + + // Example method that assigns macros only if no form controls are present + public static void AssignMacroIfNoFormControls(string inputPath, string outputPath) + { + // Load the workbook (create/load rule) + Workbook wb = new Workbook(inputPath); + + // Verify presence of form controls before enabling macros + if (ContainsFormControls(wb)) + { + Console.WriteLine("Workbook contains form controls. Macros will not be assigned."); + // Optionally, you could remove macros or take other actions here + } + else + { + Console.WriteLine("No form controls detected. Enabling macros."); + // Enable macros for the workbook + wb.Settings.EnableMacros = true; + + // Example: add a simple VBA module (requires macro-enabled format) + // Ensure the workbook is saved as a macro-enabled file + wb.Save(outputPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved with macros enabled at: {outputPath}"); + return; + } + + // Save the workbook without macros (or with macros removed) + wb.RemoveMacro(); // Ensure macros are removed if they existed + wb.Save(outputPath, SaveFormat.Xlsx); + Console.WriteLine($"Workbook saved without macros at: {outputPath}"); + } + + // Entry point for demonstration + public static void Main() + { + string sourceFile = "InputWorkbook.xlsx"; // Path to the source workbook + string resultFile = "ResultWorkbook.xlsm"; // Desired output path + + AssignMacroIfNoFormControls(sourceFile, resultFile); + } + } +} \ No newline at end of file diff --git a/macro-project/implement-a-method-that-copies-a-macro-from-one-workbook-to-another-and-updates-control-references.cs b/macro-project/implement-a-method-that-copies-a-macro-from-one-workbook-to-another-and-updates-control-references.cs new file mode 100644 index 0000000000..c38601be7a --- /dev/null +++ b/macro-project/implement-a-method-that-copies-a-macro-from-one-workbook-to-another-and-updates-control-references.cs @@ -0,0 +1,126 @@ +using System; +using System.IO; +using System.Linq; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroCopyDemo +{ + public class MacroCopier + { + /// + /// Copies macros (VBA project) from a source workbook to a destination workbook, + /// copies VBA references, enables macros in the destination and saves the result. + /// + /// Path to the macro‑enabled source workbook (e.g., .xlsm). + /// Path to the destination workbook (can be a regular .xlsx file). + /// Path where the resulting workbook will be saved (should be .xlsm to retain macros). + public static void CopyMacroAndUpdateControls(string sourcePath, string destPath, string outputPath) + { + try + { + // Verify source file exists. + if (!File.Exists(sourcePath)) + throw new FileNotFoundException("Source workbook not found.", sourcePath); + + // Load the source workbook that contains macros. + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Load or create the destination workbook. + Workbook destWorkbook; + if (File.Exists(destPath)) + { + destWorkbook = new Workbook(destPath); + } + else + { + destWorkbook = new Workbook(); // creates a new workbook with a default sheet + } + + // ----------------------------------------------------------------- + // 1. Copy the VBA project (modules, code, etc.) from source to destination. + // ----------------------------------------------------------------- + VbaProject sourceVba = sourceWorkbook.VbaProject; + VbaProject destVba = destWorkbook.VbaProject; + + // Copy the entire VBA project. + destVba.Copy(sourceVba); + + // ----------------------------------------------------------------- + // 2. Copy VBA references (external libraries) if any. + // ----------------------------------------------------------------- + VbaProjectReferenceCollection sourceRefs = sourceVba.References; + VbaProjectReferenceCollection destRefs = destVba.References; + + destRefs.Clear(); + destRefs.Copy(sourceRefs); + + // ----------------------------------------------------------------- + // 3. Enable macros in the destination workbook settings. + // ----------------------------------------------------------------- + destWorkbook.Settings.EnableMacros = true; + + // ----------------------------------------------------------------- + // 4. Copy worksheets while preserving macros. + // KeepMacros ensures any sheet‑level macro code is retained. + // ----------------------------------------------------------------- + CopyOptions copyOptions = new CopyOptions + { + KeepMacros = true + }; + + foreach (Worksheet srcSheet in sourceWorkbook.Worksheets) + { + // Ensure a unique sheet name in the destination workbook. + string newName = srcSheet.Name; + int suffix = 1; + while (destWorkbook.Worksheets.Any(ws => ws.Name.Equals(newName, StringComparison.OrdinalIgnoreCase))) + { + newName = $"{srcSheet.Name}_{suffix}"; + suffix++; + } + + // Add a new sheet with the unique name and copy contents. + Worksheet destSheet = destWorkbook.Worksheets.Add(newName); + destSheet.Copy(srcSheet, copyOptions); + } + + // ----------------------------------------------------------------- + // 5. Save the resulting workbook as a macro‑enabled file. + // ----------------------------------------------------------------- + string outputDir = Path.GetDirectoryName(outputPath); + if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir)) + { + Directory.CreateDirectory(outputDir); + } + + destWorkbook.Save(outputPath, SaveFormat.Xlsm); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error during macro copy: {ex.Message}"); + // Optionally rethrow or handle further. + throw; + } + } + + // Example usage + public static void Main() + { + try + { + string sourceFile = "SourceWithMacro.xlsm"; + string destinationFile = "EmptyWorkbook.xlsx"; // can be an existing file or a new one + string resultFile = "ResultWithMacro.xlsm"; + + CopyMacroAndUpdateControls(sourceFile, destinationFile, resultFile); + + Console.WriteLine($"Macro copied and saved to '{resultFile}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unhandled exception: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/implement-error-handling-around-vbaprojectprotect-to-capture-exceptions-when-an-empty-password-is-supplied.cs b/macro-project/implement-error-handling-around-vbaprojectprotect-to-capture-exceptions-when-an-empty-password-is-supplied.cs new file mode 100644 index 0000000000..c5ac403e28 --- /dev/null +++ b/macro-project/implement-error-handling-around-vbaprojectprotect-to-capture-exceptions-when-an-empty-password-is-supplied.cs @@ -0,0 +1,37 @@ +using System; +using Aspose.Cells; + +class VbaProjectProtectDemo +{ + static void Main() + { + // Create a new workbook (macro-enabled) + Workbook workbook = new Workbook(); + + // Attempt to protect the VBA project with an empty password + try + { + // islockedForViewing = false, password = empty string + workbook.VbaProject.Protect(false, ""); + } + catch (Exception ex) + { + // Capture and display the exception caused by an empty password + Console.WriteLine("Error protecting VBA project: " + ex.Message); + } + + // Properly protect the VBA project with a valid password + try + { + workbook.VbaProject.Protect(false, "ValidPassword123"); + Console.WriteLine("VBA project protected successfully."); + } + catch (Exception ex) + { + Console.WriteLine("Unexpected error: " + ex.Message); + } + + // Save the workbook as a macro-enabled file + workbook.Save("ProtectedDemo.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/import-an-exported-vba-project-certificate-into-another-workbook-to-share-signing-authority-across-projects.cs b/macro-project/import-an-exported-vba-project-certificate-into-another-workbook-to-share-signing-authority-across-projects.cs new file mode 100644 index 0000000000..3b3ce861ca --- /dev/null +++ b/macro-project/import-an-exported-vba-project-certificate-into-another-workbook-to-share-signing-authority-across-projects.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaCertificateImport +{ + class Program + { + static void Main() + { + try + { + // Path to the workbook that already contains a signed VBA project (source) + string sourcePath = "SignedSource.xlsm"; + + // Verify source file exists + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: '{sourcePath}'."); + return; + } + + // Load the source workbook + Workbook sourceWb = new Workbook(sourcePath); + + // Access its VBA project + VbaProject sourceVba = sourceWb.VbaProject; + + // Ensure the source VBA project is signed + if (!sourceVba.IsSigned) + { + Console.WriteLine("Source VBA project is not signed."); + return; + } + + // Retrieve the raw certificate data from the signed VBA project + byte[] certRawData = sourceVba.CertRawData; + + // Optionally, save the certificate to a file for inspection + string certFile = "ExportedVbaCertificate.cer"; + File.WriteAllBytes(certFile, certRawData); + Console.WriteLine($"Certificate raw data exported to '{certFile}' (length: {certRawData.Length})."); + + // ----------------------------------------------------------------- + // Import the exported certificate into another workbook (target) + // ----------------------------------------------------------------- + + // Path to the target workbook that needs to share the signing authority + string targetPath = "TargetWorkbook.xlsm"; + + // Verify target file exists + if (!File.Exists(targetPath)) + { + Console.WriteLine($"Target file not found: '{targetPath}'."); + return; + } + + // Load the target workbook + Workbook targetWb = new Workbook(targetPath); + + // Access its VBA project (will be created automatically for .xlsm) + VbaProject targetVba = targetWb.VbaProject; + + // Create an X509Certificate2 instance from the raw certificate data. + // Note: The raw data from a signed VBA project typically contains only the public certificate. + // To sign another workbook you need the private key (PFX). For demonstration, we assume the + // raw data includes the private key or that a corresponding PFX file is available. + X509Certificate2 certificate = new X509Certificate2(certRawData); + + // Create a DigitalSignature object using the certificate + DigitalSignature digitalSignature = new DigitalSignature(certificate, "Imported VBA Certificate", DateTime.Now); + + // Sign the target VBA project + targetVba.Sign(digitalSignature); + Console.WriteLine("Target VBA project signed using the imported certificate."); + + // Save the signed target workbook + string signedTargetPath = "TargetWorkbook_Signed.xlsm"; + targetWb.Save(signedTargetPath, SaveFormat.Xlsm); + Console.WriteLine($"Signed target workbook saved as '{signedTargetPath}'."); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/insert-a-form-control-button-onto-a-specific-worksheet-cell.cs b/macro-project/insert-a-form-control-button-onto-a-specific-worksheet-cell.cs new file mode 100644 index 0000000000..146a26b097 --- /dev/null +++ b/macro-project/insert-a-form-control-button-onto-a-specific-worksheet-cell.cs @@ -0,0 +1,27 @@ +using Aspose.Cells; +using Aspose.Cells.Drawing; + +class InsertFormControlButton +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + Worksheet sheet = workbook.Worksheets[0]; + + // Target cell where the button will be placed (e.g., B2) + int targetRow = 1; // Row index (zero‑based) + int targetColumn = 1; // Column index (zero‑based) + + // Add a Form Control button anchored to the target cell. + // Parameters: topRow, top offset (pixels), leftColumn, left offset (pixels), height (pixels), width (pixels) + Button button = sheet.Shapes.AddButton(targetRow, 0, targetColumn, 0, 30, 100); + button.Text = "Click Me"; + + // Optional: assign a macro to the button + // button.MacroName = "MyMacro"; + + // Save the workbook + workbook.Save("FormButton.xlsx"); + } +} \ No newline at end of file diff --git a/macro-project/insert-a-multiline-vba-subroutine-into-the-automation-module-to-log-workbook-opening-events.cs b/macro-project/insert-a-multiline-vba-subroutine-into-the-automation-module-to-log-workbook-opening-events.cs new file mode 100644 index 0000000000..436b426ed2 --- /dev/null +++ b/macro-project/insert-a-multiline-vba-subroutine-into-the-automation-module-to-log-workbook-opening-events.cs @@ -0,0 +1,37 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaDemo +{ + class Program + { + static void Main() + { + // Create a new workbook (default format is Xlsx) + Workbook workbook = new Workbook(); + + // Access the VBA project of the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add a procedural (standard) VBA module named "Automation" + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Procedural, "Automation"); + + // Retrieve the added module + VbaModule automationModule = vbaProject.Modules[moduleIndex]; + + // Define a multi‑line VBA subroutine that logs the workbook opening event + string vbaCode = + "Sub LogWorkbookOpen()\r\n" + + " ' This subroutine can be called from Workbook_Open event\r\n" + + " MsgBox \"Workbook opened at \" & Now\r\n" + + "End Sub"; + + // Assign the VBA code to the module + automationModule.Codes = vbaCode; + + // Save the workbook as a macro‑enabled file (Xlsm) so the VBA project is retained + workbook.Save("AutomationModuleDemo.xlsm", SaveFormat.Xlsm); + } + } +} \ No newline at end of file diff --git a/macro-project/load-a-macroenabled-workbook-from-a-memory-stream-and-verify-it-contains-at-least-one-module.cs b/macro-project/load-a-macroenabled-workbook-from-a-memory-stream-and-verify-it-contains-at-least-one-module.cs new file mode 100644 index 0000000000..9c3df965cb --- /dev/null +++ b/macro-project/load-a-macroenabled-workbook-from-a-memory-stream-and-verify-it-contains-at-least-one-module.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class MacroWorkbookCheck +{ + static void Main() + { + // ------------------------------------------------- + // 1. Create a workbook and ensure it has a VBA project + // ------------------------------------------------- + Workbook wb = new Workbook(); + + // Save as a macro‑enabled file to a temporary stream and reload + // to initialize the VbaProject (VbaProject is read‑only until a macro file is loaded) + using (MemoryStream tempStream = new MemoryStream()) + { + wb.Save(tempStream, SaveFormat.Xlsm); + tempStream.Position = 0; + wb = new Workbook(tempStream); + } + + // ------------------------------------------------- + // 2. Add a VBA module to the workbook + // ------------------------------------------------- + int moduleIndex = wb.VbaProject.Modules.Add(VbaModuleType.Class, "TestModule"); + VbaModule module = wb.VbaProject.Modules[moduleIndex]; + module.Codes = "Sub Test()\r\n MsgBox \"Hello from VBA!\"\r\nEnd Sub"; + + // ------------------------------------------------- + // 3. Save the macro‑enabled workbook to a memory stream + // ------------------------------------------------- + MemoryStream macroStream = new MemoryStream(); + wb.Save(macroStream, SaveFormat.Xlsm); + macroStream.Position = 0; // Reset for reading + + // ------------------------------------------------- + // 4. Load the workbook from the memory stream + // ------------------------------------------------- + Workbook loadedWb = new Workbook(macroStream); + + // ------------------------------------------------- + // 5. Verify that the loaded workbook contains at least one VBA module + // ------------------------------------------------- + bool hasAtLeastOneModule = loadedWb.VbaProject != null && loadedWb.VbaProject.Modules.Count > 0; + Console.WriteLine("Workbook contains VBA module: " + hasAtLeastOneModule); + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-from-a-network-share-protect-its-vba-project-and-verify-protection-after-saving.cs b/macro-project/load-a-workbook-from-a-network-share-protect-its-vba-project-and-verify-protection-after-saving.cs new file mode 100644 index 0000000000..a09675cf61 --- /dev/null +++ b/macro-project/load-a-workbook-from-a-network-share-protect-its-vba-project-and-verify-protection-after-saving.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaProtectionDemo +{ + public class Program + { + public static void Main() + { + // Path to the workbook on a network share (UNC path) + string inputPath = @"\\Server\Share\SampleWorkbook.xlsm"; + // Path where the protected workbook will be saved + string outputPath = @"\\Server\Share\SampleWorkbook_Protected.xlsm"; + + try + { + // Verify that the input file exists before attempting to load it + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input file not found: {inputPath}"); + return; + } + + // Ensure the output directory exists + string? outputDir = Path.GetDirectoryName(outputPath); + if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir)) + { + Directory.CreateDirectory(outputDir); + } + + // Load the workbook from the network share + Workbook workbook = new Workbook(inputPath); + + // Protect the VBA project if it exists (lock for viewing = false, set password) + VbaProject? vbaProject = workbook.VbaProject; + if (vbaProject != null) + { + vbaProject.Protect(false, "MyVbaPassword"); + } + else + { + Console.WriteLine("No VBA project found in the workbook."); + } + + // Save the workbook as a macro‑enabled file + workbook.Save(outputPath, SaveFormat.Xlsm); + + // Reload the saved workbook to verify protection status + Workbook reloadedWorkbook = new Workbook(outputPath); + VbaProject? reloadedVba = reloadedWorkbook.VbaProject; + + // Output verification results + if (reloadedVba != null) + { + Console.WriteLine("VBA Project IsProtected: " + reloadedVba.IsProtected); + } + else + { + Console.WriteLine("No VBA project found after saving."); + } + } + catch (Exception ex) + { + // Catch any runtime exceptions and display a friendly message + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-using-loaddatafilteroptionsvba-to-retrieve-only-vba-project-data.cs b/macro-project/load-a-workbook-using-loaddatafilteroptionsvba-to-retrieve-only-vba-project-data.cs new file mode 100644 index 0000000000..2d8224d727 --- /dev/null +++ b/macro-project/load-a-workbook-using-loaddatafilteroptionsvba-to-retrieve-only-vba-project-data.cs @@ -0,0 +1,35 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class LoadVbaOnly +{ + static void Main() + { + // Path to the source workbook (must be a macro‑enabled file to contain VBA) + string sourcePath = "input.xlsm"; + + // Create LoadOptions and assign a LoadFilter that loads only VBA projects + LoadOptions loadOptions = new LoadOptions(); + loadOptions.LoadFilter = new LoadFilter(LoadDataFilterOptions.VBA); + + // Load the workbook with the specified options + Workbook workbook = new Workbook(sourcePath, loadOptions); + + // Access the VBA project (may be null if the workbook has no VBA) + VbaProject vbaProject = workbook.VbaProject; + + if (vbaProject != null) + { + // Example: output the number of VBA modules present + Console.WriteLine("VBA Modules count: " + vbaProject.Modules.Count); + } + else + { + Console.WriteLine("No VBA project found in the workbook."); + } + + // Save the workbook (preserving the VBA project) to verify loading succeeded + workbook.Save("output.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-with-vba-data-filtered-then-enumerate-all-macro-names-present-in-the-project.cs b/macro-project/load-a-workbook-with-vba-data-filtered-then-enumerate-all-macro-names-present-in-the-project.cs new file mode 100644 index 0000000000..62be7c8e24 --- /dev/null +++ b/macro-project/load-a-workbook-with-vba-data-filtered-then-enumerate-all-macro-names-present-in-the-project.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaEnumeration +{ + class Program + { + static void Main(string[] args) + { + // Path to the macro‑enabled workbook (xlsm) + string inputPath = "sample_with_macro.xlsm"; + + try + { + // Verify that the file exists before attempting to load it + if (!File.Exists(inputPath)) + { + Console.WriteLine($"File not found: {Path.GetFullPath(inputPath)}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Check if the workbook contains any VBA macros + if (workbook.HasMacro && workbook.VbaProject != null) + { + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Enumerate all modules (each module can contain one or more macros) + Console.WriteLine("Macro modules found in the workbook:"); + foreach (VbaModule module in vbaProject.Modules) + { + // Output the module name (macro container name) + Console.WriteLine("- " + module.Name); + } + } + else + { + Console.WriteLine("The workbook does not contain any VBA macros."); + } + } + catch (Exception ex) + { + // Catch any unexpected errors and display a friendly message + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-with-vba-data-filtered-then-list-all-form-controls-that-have-macros-assigned.cs b/macro-project/load-a-workbook-with-vba-data-filtered-then-list-all-form-controls-that-have-macros-assigned.cs new file mode 100644 index 0000000000..102c4d990e --- /dev/null +++ b/macro-project/load-a-workbook-with-vba-data-filtered-then-list-all-form-controls-that-have-macros-assigned.cs @@ -0,0 +1,62 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; +using Aspose.Cells.Drawing.ActiveXControls; + +class ListFormControlsWithMacros +{ + // Custom LoadFilter that loads only VBA data from each worksheet + private class VbaLoadFilter : LoadFilter + { + public override void StartSheet(Worksheet sheet) + { + // Load only VBA projects for the sheet + LoadDataFilterOptions = LoadDataFilterOptions.VBA; + } + } + + static void Main() + { + // Prepare load options with the custom filter + LoadOptions loadOptions = new LoadOptions(); + loadOptions.LoadFilter = new VbaLoadFilter(); + + // Load the workbook (only VBA data is loaded) + Workbook workbook = new Workbook("input.xlsm", loadOptions); + + // Verify that the workbook contains macros + Console.WriteLine("Workbook HasMacro: " + workbook.HasMacro); + + // Iterate through all worksheets + foreach (Worksheet sheet in workbook.Worksheets) + { + Console.WriteLine($"Worksheet: {sheet.Name}"); + + // Iterate through all shapes in the worksheet + foreach (Shape shape in sheet.Shapes) + { + // Check if the shape hosts an ActiveX control (form control) + if (shape.ActiveXControl != null) + { + // Try to obtain the macro name assigned to the control. + // The property may be named "MacroName" or simply "Macro". + string macroName = null; + var control = shape.ActiveXControl; + var type = control.GetType(); + + var macroProp = type.GetProperty("MacroName") ?? type.GetProperty("Macro"); + if (macroProp != null) + { + macroName = macroProp.GetValue(control) as string; + } + + // If a macro is assigned, output the control information + if (!string.IsNullOrEmpty(macroName)) + { + Console.WriteLine($" Control: {shape.Name}, Type: {type.Name}, Macro: {macroName}"); + } + } + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-author-metadata-for-documentation.cs b/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-author-metadata-for-documentation.cs new file mode 100644 index 0000000000..41917f309c --- /dev/null +++ b/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-author-metadata-for-documentation.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaMetadata +{ + class Program + { + static void Main() + { + // Path to the macro‑enabled workbook to be loaded + string inputPath = "sample_with_macro.xlsm"; + + // Verify that the file exists before attempting to load it + if (!File.Exists(inputPath)) + { + Console.WriteLine($"File not found: {Path.GetFullPath(inputPath)}"); + return; + } + + try + { + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Verify that the workbook actually contains a VBA project + if (!workbook.HasMacro || workbook.VbaProject == null) + { + Console.WriteLine("The specified workbook does not contain a VBA project."); + return; + } + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Extract VBA project name (often used as the project identifier) + string vbaProjectName = vbaProject.Name ?? "(Unnamed Project)"; + + // Extract the author metadata from the built‑in document properties + string author = "(Unknown Author)"; + var authorProp = workbook.BuiltInDocumentProperties["Author"]; + if (authorProp != null && authorProp.Value != null) + { + author = authorProp.Value.ToString(); + } + + // Output the extracted information + Console.WriteLine($"VBA Project Name: {vbaProjectName}"); + Console.WriteLine($"Workbook Author (metadata): {author}"); + } + catch (Exception ex) + { + // Catch any unexpected errors and display a friendly message + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-description-property-for-metadata.cs b/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-description-property-for-metadata.cs new file mode 100644 index 0000000000..7284cd7733 --- /dev/null +++ b/macro-project/load-a-workbook-with-vba-filter-then-extract-the-vba-projects-description-property-for-metadata.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Aspose.Cells; + +class ExtractVbaDescription +{ + static void Main() + { + // Path to the macro-enabled workbook + string filePath = "sample_with_macro.xlsm"; + + // Verify that the file exists before attempting to load it + if (!File.Exists(filePath)) + { + Console.WriteLine($"File not found: {Path.GetFullPath(filePath)}"); + return; + } + + try + { + // Load the workbook from the file + Workbook workbook = new Workbook(filePath); + + // Check if the workbook contains a VBA project + if (workbook.HasMacro && workbook.VbaProject != null) + { + // Use the VBA project's Name property as its description + string vbaDescription = workbook.VbaProject.Name; + Console.WriteLine("VBA Project Description (Name): " + vbaDescription); + } + else + { + Console.WriteLine("The workbook does not contain a VBA project."); + } + } + catch (Exception ex) + { + // Handle any runtime errors gracefully + Console.WriteLine("An error occurred: " + ex.Message); + } + } +} \ No newline at end of file diff --git a/macro-project/load-an-excel-workbook-and-read-the-issigned-property-to-determine-signature-status.cs b/macro-project/load-an-excel-workbook-and-read-the-issigned-property-to-determine-signature-status.cs new file mode 100644 index 0000000000..cb3dc72f57 --- /dev/null +++ b/macro-project/load-an-excel-workbook-and-read-the-issigned-property-to-determine-signature-status.cs @@ -0,0 +1,26 @@ +using System; +using Aspose.Cells; + +namespace AsposeCellsSignatureCheck +{ + class Program + { + static void Main(string[] args) + { + // Path to the Excel file to be examined + string filePath = "input.xlsx"; + + // Load the workbook from the specified file + Workbook workbook = new Workbook(filePath); + + // Determine whether the workbook is digitally signed + bool isSigned = workbook.IsDigitallySigned; + + // Output the result + Console.WriteLine("Workbook is digitally signed: " + isSigned); + + // Clean up resources + workbook.Dispose(); + } + } +} \ No newline at end of file diff --git a/macro-project/load-an-existing-xlsm-workbook-from-a-file-path-into-a-workbook-object.cs b/macro-project/load-an-existing-xlsm-workbook-from-a-file-path-into-a-workbook-object.cs new file mode 100644 index 0000000000..c2f2abbbcb --- /dev/null +++ b/macro-project/load-an-existing-xlsm-workbook-from-a-file-path-into-a-workbook-object.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsLoadExample +{ + class Program + { + static void Main() + { + // Path to the existing XLSM workbook + string filePath = @"C:\Data\SampleWorkbook.xlsm"; + + try + { + // Ensure the file exists before loading + if (!File.Exists(filePath)) + { + Console.WriteLine($"File not found: {filePath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(filePath); + + // Show the name of the first worksheet (if any) + if (workbook.Worksheets.Count > 0) + { + Console.WriteLine("First worksheet name: " + workbook.Worksheets[0].Name); + } + else + { + Console.WriteLine("The workbook contains no worksheets."); + } + } + catch (Exception ex) + { + // Handle unexpected errors + Console.WriteLine($"Error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-an-xlsm-workbook-from-disk-and-obtain-its-vbaproject-object-for-analysis.cs b/macro-project/load-an-xlsm-workbook-from-disk-and-obtain-its-vbaproject-object-for-analysis.cs new file mode 100644 index 0000000000..98edd5c2b2 --- /dev/null +++ b/macro-project/load-an-xlsm-workbook-from-disk-and-obtain-its-vbaproject-object-for-analysis.cs @@ -0,0 +1,37 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class VbaProjectAnalysis +{ + static void Main() + { + // Path to the macro-enabled workbook + string filePath = "sample.xlsm"; + + // Load the workbook from disk using the string constructor + Workbook workbook = new Workbook(filePath); + + // Obtain the VbaProject object + VbaProject vbaProject = workbook.VbaProject; + + // Check if a VBA project exists + if (vbaProject != null) + { + // Output analysis information + Console.WriteLine("VBA Project Name: " + vbaProject.Name); + Console.WriteLine("Is Signed: " + vbaProject.IsSigned); + Console.WriteLine("Is Protected: " + vbaProject.IsProtected); + Console.WriteLine("Is Locked For Viewing: " + vbaProject.IslockedForViewing); + Console.WriteLine("Modules Count: " + vbaProject.Modules.Count); + Console.WriteLine("References Count: " + vbaProject.References.Count); + } + else + { + Console.WriteLine("No VBA project found in the workbook."); + } + + // Clean up + workbook.Dispose(); + } +} \ No newline at end of file diff --git a/macro-project/load-workbook-from-memory-stream-sign-vba-project-then-write-signed-workbook-back-to-stream.cs b/macro-project/load-workbook-from-memory-stream-sign-vba-project-then-write-signed-workbook-back-to-stream.cs new file mode 100644 index 0000000000..2b8333d5d4 --- /dev/null +++ b/macro-project/load-workbook-from-memory-stream-sign-vba-project-then-write-signed-workbook-back-to-stream.cs @@ -0,0 +1,122 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +public class VbaSigner +{ + /// + /// Loads a workbook from , signs its VBA project with the + /// certificate located at , and writes the signed workbook + /// to in macro‑enabled XLSM format. + /// + public static void SignVbaProject( + Stream inputStream, + Stream outputStream, + string certificatePath, + string certificatePassword) + { + try + { + // Ensure the input stream is positioned at the beginning + if (inputStream.CanSeek) + inputStream.Position = 0; + + // Load the workbook from the provided stream + var workbook = new Workbook(inputStream); + + // Access the VBA project (may be null if the workbook has no macros) + var vbaProject = workbook.VbaProject; + if (vbaProject != null) + { + // Verify certificate file exists + if (!File.Exists(certificatePath)) + { + Console.WriteLine($"Certificate file not found: {certificatePath}"); + return; + } + + // Load the signing certificate (must contain a private key) + var cert = new X509Certificate2(certificatePath, certificatePassword); + + // Create a DigitalSignature instance + var signature = new DigitalSignature(cert, "Signed by Aspose.Cells", DateTime.UtcNow); + + // Sign the VBA project + vbaProject.Sign(signature); + } + else + { + Console.WriteLine("The workbook does not contain a VBA project."); + } + + // Save the signed workbook to the output stream in XLSM format + workbook.Save(outputStream, SaveFormat.Xlsm); + + // Reset the output stream position for callers that will read from it + if (outputStream.CanSeek) + outputStream.Position = 0; + } + catch (Exception ex) + { + Console.WriteLine($"Error during VBA signing: {ex.Message}"); + } + } +} + +// Example usage +public class Program +{ + public static void Main() + { + try + { + const string inputPath = "UnsignedWorkbook.xlsm"; + const string outputPath = "SignedWorkbook.xlsm"; + const string certPath = "mycert.pfx"; + const string certPassword = "password"; + + // Verify input workbook exists + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input workbook not found: {inputPath}"); + return; + } + + // Verify certificate exists + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load input workbook into a memory stream + using (var fileIn = new FileStream(inputPath, FileMode.Open, FileAccess.Read)) + using (var inputMs = new MemoryStream()) + { + fileIn.CopyTo(inputMs); + + // Prepare output stream + using (var outputMs = new MemoryStream()) + { + // Sign the VBA project + VbaSigner.SignVbaProject(inputMs, outputMs, certPath, certPassword); + + // Write the signed workbook to a file for verification + File.WriteAllBytes(outputPath, outputMs.ToArray()); + + // Optional: verify signature status + var verifyWb = new Workbook(new MemoryStream(outputMs.ToArray())); + Console.WriteLine("Is Signed: " + verifyWb.VbaProject.IsSigned); + Console.WriteLine("Is Valid Signed: " + verifyWb.VbaProject.IsValidSigned); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Unhandled exception: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/load-workbook-using-loadoptions-to-omit-vba-project-and-verify-macros-are-excluded.cs b/macro-project/load-workbook-using-loadoptions-to-omit-vba-project-and-verify-macros-are-excluded.cs new file mode 100644 index 0000000000..8786f40289 --- /dev/null +++ b/macro-project/load-workbook-using-loadoptions-to-omit-vba-project-and-verify-macros-are-excluded.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsMacroOmitDemo +{ + // Custom load filter that loads everything except VBA projects + class NoVbaLoadFilter : LoadFilter + { + public override void StartSheet(Worksheet sheet) + { + // Load all data but exclude VBA (bitwise remove VBA flag) + LoadDataFilterOptions = LoadDataFilterOptions.All & ~LoadDataFilterOptions.VBA; + } + } + + class Program + { + static void Main() + { + // Path to a macro‑enabled workbook (e.g., .xlsm) that contains VBA code + string inputPath = "sample_with_macro.xlsm"; + + // Verify that the input file exists + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input file not found: {inputPath}"); + return; + } + + try + { + // Configure load options to use the custom filter that skips VBA + LoadOptions loadOptions = new LoadOptions + { + LoadFilter = new NoVbaLoadFilter() + }; + + // Load the workbook with the specified options + Workbook workbook = new Workbook(inputPath, loadOptions); + + // Verify that macros have been omitted + Console.WriteLine("HasMacro after load with filter: " + workbook.HasMacro); // Expected: False + + // Optionally save the macro‑free workbook + string outputPath = "macro_free.xlsx"; + workbook.Save(outputPath, SaveFormat.Xlsx); + Console.WriteLine("Macro‑free workbook saved to: " + outputPath); + } + catch (Exception ex) + { + Console.WriteLine("An error occurred: " + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-exclude-unsigned-macros-during-import.cs b/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-exclude-unsigned-macros-during-import.cs new file mode 100644 index 0000000000..dd139c78e8 --- /dev/null +++ b/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-exclude-unsigned-macros-during-import.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using Aspose.Cells; + +class Program +{ + static void Main() + { + const string inputPath = "input.xlsm"; + const string outputPath = "output.xlsx"; + + // Verify that the input file exists. + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Error: Input file not found – {inputPath}"); + return; + } + + try + { + // Load the workbook. No explicit LoadOptions are required for .xlsm files. + Workbook workbook = new Workbook(inputPath); + + // Display macro presence information. + Console.WriteLine("HasMacro after load: " + workbook.HasMacro); + + // Save as a macro‑free XLSX file. + workbook.Save(outputPath, SaveFormat.Xlsx); + Console.WriteLine($"Workbook saved to {outputPath}"); + } + catch (Exception ex) + { + // Handle any runtime errors. + Console.WriteLine("An error occurred: " + ex.Message); + } + } +} \ No newline at end of file diff --git a/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-include-only-signed-macros-for-further-processing.cs b/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-include-only-signed-macros-for-further-processing.cs new file mode 100644 index 0000000000..2e293e99a7 --- /dev/null +++ b/macro-project/load-workbook-with-loadoptionsfiltervbaproject-to-include-only-signed-macros-for-further-processing.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class LoadSignedVbaWorkbook +{ + static void Main() + { + try + { + const string inputPath = "SignedWorkbook.xlsm"; + const string outputPath = "ProcessedWorkbook.xlsm"; + + // Verify that the input file exists to avoid FileNotFoundException. + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input file not found: {inputPath}"); + return; + } + + // Load the workbook. Aspose.Cells automatically detects the format. + Workbook workbook = new Workbook(inputPath); + + // Check if a signed VBA project was loaded. + if (workbook.VbaProject != null && workbook.VbaProject.IsSigned) + { + Console.WriteLine("VBA project is signed."); + Console.WriteLine("Signature valid: " + workbook.VbaProject.IsValidSigned); + } + else + { + Console.WriteLine("No signed VBA project loaded."); + } + + // Perform further processing on the workbook here... + + // Save the processed workbook. + workbook.Save(outputPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved to: {outputPath}"); + } + catch (Exception ex) + { + // Log any unexpected errors. + Console.WriteLine("An error occurred: " + ex.Message); + } + } +} \ No newline at end of file diff --git a/macro-project/log-a-warning-if-the-vba-project-is-locked-for-viewing-after-checking-its-protection-status.cs b/macro-project/log-a-warning-if-the-vba-project-is-locked-for-viewing-after-checking-its-protection-status.cs new file mode 100644 index 0000000000..ff810a067d --- /dev/null +++ b/macro-project/log-a-warning-if-the-vba-project-is-locked-for-viewing-after-checking-its-protection-status.cs @@ -0,0 +1,32 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class CheckVbaProjectLock +{ + static void Main() + { + // Load an existing workbook (replace with your file path) + Workbook workbook = new Workbook("input.xlsm"); + + // Get the VBA project associated with the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Determine if the VBA project is protected and if it is locked for viewing + bool isProtected = vbaProject.IsProtected; + bool isLockedForViewing = vbaProject.IslockedForViewing; + + // Log a warning when the project is both protected and locked for viewing + if (isProtected && isLockedForViewing) + { + Console.WriteLine("Warning: VBA project is protected and locked for viewing."); + } + else + { + Console.WriteLine($"VBA project status - Protected: {isProtected}, LockedForViewing: {isLockedForViewing}"); + } + + // Save the workbook (no modifications made, just to follow lifecycle) + workbook.Save("output.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/log-detailed-information-about-each-macro-assignment-including-worksheet-name-control-id-and-macro-name.cs b/macro-project/log-detailed-information-about-each-macro-assignment-including-worksheet-name-control-id-and-macro-name.cs new file mode 100644 index 0000000000..ae4466df3e --- /dev/null +++ b/macro-project/log-detailed-information-about-each-macro-assignment-including-worksheet-name-control-id-and-macro-name.cs @@ -0,0 +1,50 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; + +class MacroLogger +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Enable macros for the workbook (optional but recommended) + workbook.Settings.EnableMacros = true; + + // ---------- Worksheet 1 ---------- + Worksheet sheet1 = workbook.Worksheets[0]; + sheet1.Name = "SheetOne"; + + // Add a rectangle shape and assign a macro + Shape rectShape = sheet1.Shapes.AddRectangle(1, 1, 100, 100, 0, 0); + rectShape.Name = "Button1"; // Control ID + rectShape.MacroName = "MacroOne"; // Macro name + + // ---------- Worksheet 2 ---------- + int newSheetIdx = workbook.Worksheets.Add(); + Worksheet sheet2 = workbook.Worksheets[newSheetIdx]; + sheet2.Name = "SheetTwo"; + + // Add an oval shape and assign a macro + Shape ovalShape = sheet2.Shapes.AddOval(2, 2, 80, 80, 0, 0); + ovalShape.Name = "Button2"; // Control ID + ovalShape.MacroName = "MacroTwo"; // Macro name + + // Log detailed information about each macro assignment + foreach (Worksheet ws in workbook.Worksheets) + { + foreach (Shape shp in ws.Shapes) + { + // Only log shapes that have a macro assigned + if (!string.IsNullOrEmpty(shp.MacroName)) + { + Console.WriteLine($"Worksheet: {ws.Name}, Control ID: {shp.Name}, Macro Name: {shp.MacroName}"); + } + } + } + + // Save the workbook as a macro‑enabled file + workbook.Save("MacroLogDemo.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/log-the-signing-result-to-console-output-indicating-success-or-failure-for-each-workbook.cs b/macro-project/log-the-signing-result-to-console-output-indicating-success-or-failure-for-each-workbook.cs new file mode 100644 index 0000000000..4c6da120d0 --- /dev/null +++ b/macro-project/log-the-signing-result-to-console-output-indicating-success-or-failure-for-each-workbook.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; +using System.Security.Cryptography.X509Certificates; + +namespace AsposeCellsDigitalSignatureDemo +{ + class Program + { + static void Main(string[] args) + { + // Paths of workbooks to be signed + string[] workbookPaths = new string[] + { + "Workbook1.xlsx", + "Workbook2.xlsx", + // add more paths as needed + }; + + // Digital certificate used for signing + string certificatePath = "certificate.pfx"; + string certificatePassword = "password"; + + // Load the certificate once, after verifying the file exists + X509Certificate2 certificate; + try + { + if (!File.Exists(certificatePath)) + { + Console.WriteLine($"Certificate file not found: {certificatePath}"); + return; + } + + certificate = new X509Certificate2(certificatePath, certificatePassword); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load certificate: {ex.Message}"); + return; + } + + foreach (string inputPath in workbookPaths) + { + try + { + // Verify workbook file exists before loading + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Workbook file not found: {inputPath}"); + continue; + } + + // Load the workbook + using (Workbook workbook = new Workbook(inputPath)) + { + // Create a digital signature collection and add a signature + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + DigitalSignature signature = new DigitalSignature(certificate, "Signed by Aspose.Cells", DateTime.Now); + signatures.Add(signature); + + // Apply the digital signature to the workbook + workbook.SetDigitalSignature(signatures); + + // Save the signed workbook (appending "_signed" to the original name) + string outputPath = Path.Combine( + Path.GetDirectoryName(inputPath) ?? string.Empty, + Path.GetFileNameWithoutExtension(inputPath) + "_signed.xlsx"); + + workbook.Save(outputPath); + + // Verify signing result + bool isSigned = workbook.IsDigitallySigned; + Console.WriteLine($"Workbook '{inputPath}' signing {(isSigned ? "succeeded" : "failed")}."); + } + } + catch (Exception ex) + { + // Log any failure during the signing process + Console.WriteLine($"Workbook '{inputPath}' signing failed: {ex.Message}"); + } + } + } + } +} \ No newline at end of file diff --git a/macro-project/open-a-macro-enabled-workbook-while-skipping-worksheet-content-by-applying-the-vba-filter.cs b/macro-project/open-a-macro-enabled-workbook-while-skipping-worksheet-content-by-applying-the-vba-filter.cs new file mode 100644 index 0000000000..e16e0d8df4 --- /dev/null +++ b/macro-project/open-a-macro-enabled-workbook-while-skipping-worksheet-content-by-applying-the-vba-filter.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using Aspose.Cells; + +class OpenMacroWorkbook +{ + static void Main() + { + // Path to the macro‑enabled workbook + string filePath = "sample_with_macro.xlsm"; + + try + { + // Prevent FileNotFoundException + if (!File.Exists(filePath)) + { + Console.WriteLine($"File not found: {Path.GetFullPath(filePath)}"); + return; + } + + // Load only workbook structure and VBA, skip cell data + LoadOptions loadOptions = new LoadOptions + { + LoadFilter = new LoadFilter(LoadDataFilterOptions.Structure | LoadDataFilterOptions.VBA) + }; + + // Load the workbook with the specified options + Workbook workbook = new Workbook(filePath, loadOptions); + + // Output whether the workbook contains macros + Console.WriteLine("HasMacro: " + workbook.HasMacro); + } + catch (Exception ex) + { + // Runtime safety + Console.WriteLine("Error: " + ex.Message); + } + } +} \ No newline at end of file diff --git a/macro-project/overwrite-original-workbook-after-successful-signing-when-backup-is-not-required-by-policy.cs b/macro-project/overwrite-original-workbook-after-successful-signing-when-backup-is-not-required-by-policy.cs new file mode 100644 index 0000000000..a64341195e --- /dev/null +++ b/macro-project/overwrite-original-workbook-after-successful-signing-when-backup-is-not-required-by-policy.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsExamples +{ + public class SignAndOverwriteWorkbook + { + /// + /// Signs the workbook with a digital signature and overwrites the original file. + /// No backup copy is created. + /// + /// Full path to the workbook to be signed. + /// Full path to the PFX certificate file. + /// Password for the certificate. + public static void Run(string workbookPath, string certificatePath, string certificatePassword) + { + try + { + // Verify that the workbook file exists + if (!File.Exists(workbookPath)) + throw new FileNotFoundException("Workbook file not found.", workbookPath); + + // Verify that the certificate file exists + if (!File.Exists(certificatePath)) + throw new FileNotFoundException("Certificate file not found.", certificatePath); + + // Load the existing workbook + Workbook workbook = new Workbook(workbookPath); + + // Load the certificate data (PFX file) + byte[] certData = File.ReadAllBytes(certificatePath); + + // Create a digital signature using the certificate data + DigitalSignature signature = new DigitalSignature(certData, certificatePassword, "Aspose.Signature", DateTime.Now); + + // Create a collection and add the signature + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + signatures.Add(signature); + + // Apply the digital signature to the workbook + workbook.SetDigitalSignature(signatures); + + // Overwrite the original workbook file with the signed version + workbook.Save(workbookPath); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error signing workbook: {ex.Message}"); + } + } + } + + // Entry point for the console application + public class Program + { + public static void Main(string[] args) + { + // Expected arguments: workbookPath, certificatePath, certificatePassword + if (args.Length < 3) + { + Console.WriteLine("Usage: AsposeCellsRunner "); + return; + } + + string workbookPath = args[0]; + string certificatePath = args[1]; + string certificatePassword = args[2]; + + SignAndOverwriteWorkbook.Run(workbookPath, certificatePath, certificatePassword); + } + } +} \ No newline at end of file diff --git a/macro-project/preserve-existing-macros-while-copying-userform-storage-to-ensure-functionality-remains-unchanged.cs b/macro-project/preserve-existing-macros-while-copying-userform-storage-to-ensure-functionality-remains-unchanged.cs new file mode 100644 index 0000000000..1e8886b7e0 --- /dev/null +++ b/macro-project/preserve-existing-macros-while-copying-userform-storage-to-ensure-functionality-remains-unchanged.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroCopy +{ + public class PreserveMacrosAndUserForms + { + // Entry point required for console application + public static void Main(string[] args) + { + try + { + Run(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + + public static void Run() + { + const string sourcePath = "SourceWithMacros.xlsm"; + const string destPath = "DestinationWithMacrosAndUserForms.xlsm"; + + // Verify source file exists to avoid FileNotFoundException + if (!File.Exists(sourcePath)) + throw new FileNotFoundException($"Source workbook not found: {sourcePath}"); + + // Load the source workbook that contains macros and userforms + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Create an empty destination workbook + Workbook destWorkbook = new Workbook(); + + // Configure copy options to keep macros during the copy operation + CopyOptions copyOptions = new CopyOptions + { + KeepMacros = true + }; + + // Copy the entire workbook (worksheets, data, macros, etc.) to the destination + destWorkbook.Copy(sourceWorkbook, copyOptions); + + // Copy VBA references (libraries) from source to destination + destWorkbook.VbaProject.References.Copy(sourceWorkbook.VbaProject.References); + + // Iterate through all VBA modules in the source workbook + foreach (VbaModule srcModule in sourceWorkbook.VbaProject.Modules) + { + // Retrieve the designer storage for the current module (null for non‑UserForm modules) + byte[] designerStorage = sourceWorkbook.VbaProject.Modules.GetDesignerStorage(srcModule.Name); + + // If designer storage exists, the module is a UserForm; copy it to the destination + if (designerStorage != null && designerStorage.Length > 0) + { + // Add the UserForm to the destination VBA project with its code and designer data + destWorkbook.VbaProject.Modules.AddUserForm( + srcModule.Name, // UserForm name + srcModule.Codes, // VBA code associated with the UserForm + designerStorage // Binary designer storage (.frx data) + ); + } + } + + // Save the destination workbook; macros and UserForms are preserved + destWorkbook.Save(destPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved successfully to '{destPath}'."); + } + } +} \ No newline at end of file diff --git a/macro-project/programmatically-check-each-workbook-in-a-collection-for-unsigned-vba-projects-and-log-file-names.cs b/macro-project/programmatically-check-each-workbook-in-a-collection-for-unsigned-vba-projects-and-log-file-names.cs new file mode 100644 index 0000000000..0cac4e6102 --- /dev/null +++ b/macro-project/programmatically-check-each-workbook-in-a-collection-for-unsigned-vba-projects-and-log-file-names.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsVbaCheck +{ + public class UnsignedVbaChecker + { + // Checks a collection of workbook file paths for unsigned VBA projects. + // Logs the file names of workbooks that contain macros but are not signed. + public static void Run(IEnumerable workbookPaths, string logFilePath) + { + try + { + // Ensure the log file is empty before starting. + File.WriteAllText(logFilePath, string.Empty); + + foreach (string path in workbookPaths) + { + // Skip non‑existent files. + if (!File.Exists(path)) + { + Console.WriteLine($"File not found: {path}"); + continue; + } + + try + { + // Load the workbook. + Workbook workbook = new Workbook(path); + + // Determine if the workbook contains a VBA project. + if (workbook.HasMacro) + { + // Check the signature status. + bool isSigned = workbook.VbaProject.IsSigned; + + if (!isSigned) + { + // Log the unsigned workbook name. + string fileName = Path.GetFileName(path); + Console.WriteLine($"Unsigned VBA project: {fileName}"); + File.AppendAllText(logFilePath, fileName + Environment.NewLine); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Error processing file '{path}': {ex.Message}"); + } + } + + Console.WriteLine($"Logging complete. Results saved to: {logFilePath}"); + } + catch (Exception ex) + { + Console.WriteLine($"Fatal error: {ex.Message}"); + } + } + } + + public class Program + { + // Entry point for the console application. + public static void Main(string[] args) + { + try + { + if (args.Length < 2) + { + Console.WriteLine("Usage: AsposeCellsVbaCheck [ ...]"); + return; + } + + string logFilePath = args[0]; + var workbookPaths = new List(args.Length - 1); + for (int i = 1; i < args.Length; i++) + { + workbookPaths.Add(args[i]); + } + + UnsignedVbaChecker.Run(workbookPaths, logFilePath); + } + catch (Exception ex) + { + Console.WriteLine($"Unhandled exception: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/programmatically-rename-a-form-control-button-while-preserving-its-assigned-macro-reference.cs b/macro-project/programmatically-rename-a-form-control-button-while-preserving-its-assigned-macro-reference.cs new file mode 100644 index 0000000000..2cf261cedf --- /dev/null +++ b/macro-project/programmatically-rename-a-form-control-button-while-preserving-its-assigned-macro-reference.cs @@ -0,0 +1,41 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; + +class RenameButtonDemo +{ + static void Main() + { + // Load the workbook that contains the button + Workbook workbook = new Workbook("input.xlsx"); + + // Access the worksheet where the button resides + Worksheet worksheet = workbook.Worksheets[0]; + + // Locate the button by its current name + Button button = null; + foreach (Shape shape in worksheet.Shapes) + { + if (shape is Button && shape.Name == "OldButton") + { + button = (Button)shape; + break; + } + } + + if (button != null) + { + // Store the existing macro reference + string existingMacro = button.MacroName; + + // Rename the button + button.Name = "NewButton"; + + // Reassign the macro name to ensure it remains linked + button.MacroName = existingMacro; + } + + // Save the modified workbook + workbook.Save("output.xlsx"); + } +} \ No newline at end of file diff --git a/macro-project/protect-all-xlsm-files-in-a-directory-applying-passwords-only-to-unprotected-vba-projects.cs b/macro-project/protect-all-xlsm-files-in-a-directory-applying-passwords-only-to-unprotected-vba-projects.cs new file mode 100644 index 0000000000..a3b9278e1e --- /dev/null +++ b/macro-project/protect-all-xlsm-files-in-a-directory-applying-passwords-only-to-unprotected-vba-projects.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ProtectVbaProjects +{ + static void Main(string[] args) + { + // Directory containing the XLSM files. Change as needed or pass as first argument. + string folderPath = args.Length > 0 ? args[0] : @"C:\ExcelFiles"; + + // Password to apply to unprotected VBA projects. + const string vbaPassword = "MyVbaPassword"; + + // Get all .xlsm files in the specified directory. + string[] files = Directory.GetFiles(folderPath, "*.xlsm", SearchOption.TopDirectoryOnly); + + foreach (string filePath in files) + { + // Load the workbook. + Workbook workbook = new Workbook(filePath); + + // Check if the VBA project is already protected. + if (!workbook.VbaProject.IsProtected) + { + // Protect the VBA project without locking it for viewing. + workbook.VbaProject.Protect(false, vbaPassword); + + // Save the workbook, overwriting the original file. + workbook.Save(filePath, SaveFormat.Xlsm); + Console.WriteLine($"Protected VBA project in: {Path.GetFileName(filePath)}"); + } + else + { + Console.WriteLine($"VBA project already protected in: {Path.GetFileName(filePath)}"); + } + + // Release resources. + workbook.Dispose(); + } + } +} \ No newline at end of file diff --git a/macro-project/remove-a-specified-module-using-modulesremoveat-and-save-the-workbook-to-apply-changes.cs b/macro-project/remove-a-specified-module-using-modulesremoveat-and-save-the-workbook-to-apply-changes.cs new file mode 100644 index 0000000000..1aaea10742 --- /dev/null +++ b/macro-project/remove-a-specified-module-using-modulesremoveat-and-save-the-workbook-to-apply-changes.cs @@ -0,0 +1,42 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class RemoveVbaModuleByIndexDemo + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + + public static void Run() + { + // Create a new macro‑enabled workbook + Workbook workbook = new Workbook(); + + // Access the VBA project of the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Add a new procedural VBA module with a specific name + int moduleIndex = vbaProject.Modules.Add(VbaModuleType.Procedural, "SampleModule"); + + // Add some VBA code to the module + vbaProject.Modules[moduleIndex].Codes = "Sub HelloWorld()\r\n MsgBox \"Hello World\"\r\nEnd Sub"; + + // Remove the module by its index + vbaProject.Modules.RemoveAt(moduleIndex); + + // Save the workbook as a macro‑enabled file + workbook.Save("WorkbookAfterModuleRemoval.xlsm", SaveFormat.Xlsm); + } + } +} \ No newline at end of file diff --git a/macro-project/remove-any-module-named-temp-from-a-collection-of-workbooks-and-save-the-modified-files.cs b/macro-project/remove-any-module-named-temp-from-a-collection-of-workbooks-and-save-the-modified-files.cs new file mode 100644 index 0000000000..f49773197c --- /dev/null +++ b/macro-project/remove-any-module-named-temp-from-a-collection-of-workbooks-and-save-the-modified-files.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class RemoveTempVbaModules + { + // Removes a VBA module named "Temp" from each workbook in the collection and saves the changes. + public static void Run(IEnumerable workbookPaths) + { + foreach (string path in workbookPaths) + { + try + { + // Verify the file exists to avoid FileNotFoundException + if (!File.Exists(path)) + { + Console.WriteLine($"File not found: {path}"); + continue; + } + + // Load the workbook from file + using (Workbook workbook = new Workbook(path)) + { + // Access the VBA project (may be empty) + VbaProject vbaProject = workbook.VbaProject; + + // Attempt to remove the module named "Temp" if it exists + // The Remove method does not throw if the name is not found + vbaProject?.Modules?.Remove("Temp"); + + // Save the modified workbook (overwrites the original file) + workbook.Save(path, SaveFormat.Xlsx); + } + + Console.WriteLine($"Processed workbook: {path}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error processing '{path}': {ex.Message}"); + } + } + } + } + + public class Program + { + // Entry point required for the application + public static void Main(string[] args) + { + try + { + if (args == null || args.Length == 0) + { + Console.WriteLine("Please provide one or more workbook file paths as arguments."); + return; + } + + // Pass the provided file paths to the processing method + RemoveTempVbaModules.Run(args); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/remove-digital-signature-from-vba-project-by-clearing-certificate-and-verify-issigned-becomes-false.cs b/macro-project/remove-digital-signature-from-vba-project-by-clearing-certificate-and-verify-issigned-becomes-false.cs new file mode 100644 index 0000000000..1e90ddcfc2 --- /dev/null +++ b/macro-project/remove-digital-signature-from-vba-project-by-clearing-certificate-and-verify-issigned-becomes-false.cs @@ -0,0 +1,32 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaSignatureRemoval +{ + class Program + { + static void Main() + { + // Path to the workbook that contains a signed VBA project + string signedPath = "SignedVbaProject.xlsm"; + + // Load the signed workbook + Workbook signedWorkbook = new Workbook(signedPath); + + // Verify that the VBA project is currently signed + Console.WriteLine("Before removal - VBA project IsSigned: " + signedWorkbook.VbaProject.IsSigned); + + // Remove the digital signature from the workbook (this also clears the VBA project signature) + signedWorkbook.RemoveDigitalSignature(); + + // Save the workbook without the signature + string unsignedPath = "UnsignedVbaProject.xlsm"; + signedWorkbook.Save(unsignedPath, SaveFormat.Xlsm); + + // Reload the saved workbook to verify the signature state + Workbook unsignedWorkbook = new Workbook(unsignedPath); + Console.WriteLine("After removal - VBA project IsSigned: " + unsignedWorkbook.VbaProject.IsSigned); + } + } +} \ No newline at end of file diff --git a/macro-project/rename-an-existing-vba-module-to-dataprocessor-by-setting-its-name-property-before-saving.cs b/macro-project/rename-an-existing-vba-module-to-dataprocessor-by-setting-its-name-property-before-saving.cs new file mode 100644 index 0000000000..85a0acf1b1 --- /dev/null +++ b/macro-project/rename-an-existing-vba-module-to-dataprocessor-by-setting-its-name-property-before-saving.cs @@ -0,0 +1,25 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class RenameVbaModule +{ + static void Main() + { + // Create a new workbook + Workbook wb = new Workbook(); + + // Add a procedural VBA module with an initial name + int moduleIndex = wb.VbaProject.Modules.Add(VbaModuleType.Procedural, "OldName"); + VbaModule module = wb.VbaProject.Modules[moduleIndex]; + + // (Optional) Add some VBA code to the module + module.Codes = "Sub Test()\n MsgBox \"Hello\"\nEnd Sub"; + + // Rename the module to "DataProcessor" + module.Name = "DataProcessor"; + + // Save the workbook as a macro-enabled file + wb.Save("RenamedModule.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/resign-vba-project-after-code-changes-to-restore-a-valid-digital-signature-status.cs b/macro-project/resign-vba-project-after-code-changes-to-restore-a-valid-digital-signature-status.cs new file mode 100644 index 0000000000..34c304494e --- /dev/null +++ b/macro-project/resign-vba-project-after-code-changes-to-restore-a-valid-digital-signature-status.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsExamples +{ + public class ReSignVbaProjectDemo + { + public static void Main() + { + Run(); + } + + public static void Run() + { + try + { + const string workbookPath = "OriginalWithVba.xlsm"; + const string certPath = "MyCertificate.pfx"; + const string certPassword = "certificatePassword"; + + // Verify that the workbook file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Verify that the certificate file exists + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load the workbook that contains a VBA project + Workbook workbook = new Workbook(workbookPath); + + // Get the VBA project from the workbook + VbaProject vbaProject = workbook.VbaProject; + + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Modify VBA code if there is at least one module + if (vbaProject.Modules.Count > 0) + { + VbaModule module = vbaProject.Modules[0]; + // Append a comment to indicate that the code was changed + module.Codes += "\n' Modified by ReSignVbaProjectDemo"; + } + + // Load the signing certificate + X509Certificate2 certificate = new X509Certificate2(certPath, certPassword); + + // Create a digital signature object + DigitalSignature digitalSignature = new DigitalSignature( + certificate, + "Re-signed after code changes", + DateTime.Now); + + // Sign the VBA project with the new digital signature + vbaProject.Sign(digitalSignature); + + // Save the workbook (macro-enabled) to a memory stream + using (MemoryStream stream = new MemoryStream()) + { + workbook.Save(stream, SaveFormat.Xlsm); + stream.Position = 0; // Reset stream position for reading + + // Reload the workbook from the stream to verify signature status + Workbook verifyWorkbook = new Workbook(stream); + Console.WriteLine("VBA Project IsSigned: " + verifyWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + verifyWorkbook.VbaProject.IsValidSigned); + } + } + catch (Exception ex) + { + Console.WriteLine("An error occurred: " + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/macro-project/retrieve-the-list-of-com-library-references-from-the-vba-project-and-log-each-reference-name.cs b/macro-project/retrieve-the-list-of-com-library-references-from-the-vba-project-and-log-each-reference-name.cs new file mode 100644 index 0000000000..338a4ba1de --- /dev/null +++ b/macro-project/retrieve-the-list-of-com-library-references-from-the-vba-project-and-log-each-reference-name.cs @@ -0,0 +1,30 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class RetrieveVbaReferences +{ + static void Main() + { + // Load a macro-enabled workbook (replace with your file path) + Workbook workbook = new Workbook("input.xlsm"); + + // Check if the workbook contains a VBA project + if (workbook.VbaProject != null) + { + // Get the collection of VBA references + VbaProjectReferenceCollection references = workbook.VbaProject.References; + + // Iterate through each reference and log its name + for (int i = 0; i < references.Count; i++) + { + VbaProjectReference reference = references[i]; + Console.WriteLine($"Reference {i + 1}: {reference.Name}"); + } + } + else + { + Console.WriteLine("The workbook does not contain a VBA project."); + } + } +} \ No newline at end of file diff --git a/macro-project/retrieve-the-vba-project-from-the-loaded-workbook-via-workbookvbaproject.cs b/macro-project/retrieve-the-vba-project-from-the-loaded-workbook-via-workbookvbaproject.cs new file mode 100644 index 0000000000..2e0a0a802a --- /dev/null +++ b/macro-project/retrieve-the-vba-project-from-the-loaded-workbook-via-workbookvbaproject.cs @@ -0,0 +1,28 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class Program +{ + static void Main() + { + // Load an existing macro-enabled workbook + Workbook workbook = new Workbook("input.xlsm"); + + // Retrieve the VBA project from the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Display some information about the VBA project + if (vbaProject != null) + { + Console.WriteLine("VBA Project Name: " + vbaProject.Name); + Console.WriteLine("Is Signed: " + vbaProject.IsSigned); + Console.WriteLine("Is Protected: " + vbaProject.IsProtected); + Console.WriteLine("Is Locked For Viewing: " + vbaProject.IslockedForViewing); + } + else + { + Console.WriteLine("The workbook does not contain a VBA project."); + } + } +} \ No newline at end of file diff --git a/macro-project/save-signed-workbook-to-network-location-via-stream-to-enable-centralized-access-for-users.cs b/macro-project/save-signed-workbook-to-network-location-via-stream-to-enable-centralized-access-for-users.cs new file mode 100644 index 0000000000..b8ee1466ea --- /dev/null +++ b/macro-project/save-signed-workbook-to-network-location-via-stream-to-enable-centralized-access-for-users.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +class SaveSignedWorkbookToNetwork +{ + static void Main() + { + try + { + // Verify certificate file exists + string certPath = @"C:\Certificates\sample.pfx"; // adjust path as needed + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load certificate data + string certPassword = "123456"; // certificate password + byte[] certData = File.ReadAllBytes(certPath); + DigitalSignature signature = new DigitalSignature(certData, certPassword, "Demo Signer", DateTime.UtcNow); + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + signatures.Add(signature); + + // Create workbook and add data + using (Workbook workbook = new Workbook()) + { + Worksheet sheet = workbook.Worksheets[0]; + sheet.Cells["A1"].PutValue("Signed Workbook"); + sheet.Cells["B1"].PutValue(DateTime.Now); + + // Apply digital signature + workbook.SetDigitalSignature(signatures); + + // Define UNC network path + string networkFilePath = @"\\Server\SharedFolder\SignedWorkbook.xlsx"; + + // Ensure target directory exists + string networkDir = Path.GetDirectoryName(networkFilePath); + if (!Directory.Exists(networkDir)) + { + Directory.CreateDirectory(networkDir); + } + + // Save signed workbook to network location via stream + using (FileStream networkStream = new FileStream(networkFilePath, FileMode.Create, FileAccess.Write)) + { + workbook.Save(networkStream, SaveFormat.Xlsx); + } + } + + Console.WriteLine("Signed workbook successfully saved to network location."); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/save-signed-workbook-under-new-filename-to-preserve-original-file-and-maintain-audit-trail.cs b/macro-project/save-signed-workbook-under-new-filename-to-preserve-original-file-and-maintain-audit-trail.cs new file mode 100644 index 0000000000..761734ef83 --- /dev/null +++ b/macro-project/save-signed-workbook-under-new-filename-to-preserve-original-file-and-maintain-audit-trail.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsExamples +{ + public class SaveSignedWorkbookDemo + { + public static void Main(string[] args) + { + Run(); + } + + public static void Run() + { + // Path to the original signed workbook + string originalPath = "SignedOriginal.xlsx"; + + // Verify the source file exists to avoid FileNotFoundException + if (!File.Exists(originalPath)) + { + Console.WriteLine($"Source file not found: {originalPath}"); + return; + } + + try + { + // Load the signed workbook + Workbook workbook = new Workbook(originalPath); + + // Optional: verify that the workbook is digitally signed + if (workbook.IsDigitallySigned) + { + Console.WriteLine("Original workbook is digitally signed."); + } + else + { + Console.WriteLine("Original workbook is NOT digitally signed."); + } + + // Define the new file name for the audit copy + string auditCopyPath = "SignedAuditCopy.xlsx"; + + // Save the workbook under the new name (preserves the signature) + workbook.Save(auditCopyPath); + Console.WriteLine($"Workbook saved as audit copy: {auditCopyPath}"); + } + catch (Exception ex) + { + // Catch any runtime exceptions and display the error + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/save-the-modified-workbook-as-an-xlsm-file-to-preserve-the-added-vba-code.cs b/macro-project/save-the-modified-workbook-as-an-xlsm-file-to-preserve-the-added-vba-code.cs new file mode 100644 index 0000000000..23d0814826 --- /dev/null +++ b/macro-project/save-the-modified-workbook-as-an-xlsm-file-to-preserve-the-added-vba-code.cs @@ -0,0 +1,33 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaDemo +{ + class Program + { + static void Main() + { + // Create a new workbook (uses the provided Workbook() constructor) + Workbook workbook = new Workbook(); + + // Access the VBA project (read‑only property, but we can add modules after saving as macro‑enabled) + // Ensure the workbook is macro‑enabled by saving it as Xlsm and reloading + string tempPath = "temp.xlsm"; + workbook.Save(tempPath, SaveFormat.Xlsm); + workbook = new Workbook(tempPath); + System.IO.File.Delete(tempPath); + + // Add a new VBA module to the project + int moduleIndex = workbook.VbaProject.Modules.Add(VbaModuleType.Class, "TestModule"); + VbaModule module = workbook.VbaProject.Modules[moduleIndex]; + module.Codes = "Sub Test()\r\n MsgBox \"Hello from VBA!\"\r\nEnd Sub"; + + // Save the workbook as a macro‑enabled file to preserve the VBA code + string outputPath = "VbaEnabledWorkbook.xlsm"; + workbook.Save(outputPath, SaveFormat.Xlsm); + + Console.WriteLine($"Workbook saved with VBA code at: {outputPath}"); + } + } +} \ No newline at end of file diff --git a/macro-project/save-the-signed-workbook-to-a-new-location-ensuring-the-digital-signature-remains-intact.cs b/macro-project/save-the-signed-workbook-to-a-new-location-ensuring-the-digital-signature-remains-intact.cs new file mode 100644 index 0000000000..3d8c1967c3 --- /dev/null +++ b/macro-project/save-the-signed-workbook-to-a-new-location-ensuring-the-digital-signature-remains-intact.cs @@ -0,0 +1,33 @@ +using System; +using Aspose.Cells; + +class SaveSignedWorkbook +{ + static void Main() + { + // Path to the existing digitally signed workbook + string sourcePath = "SignedWorkbook.xlsx"; + + // Path where the copy will be saved + string destinationPath = "SignedWorkbookCopy.xlsx"; + + // Load the signed workbook from disk + Workbook workbook = new Workbook(sourcePath); + + // Optional: check if the workbook is digitally signed + if (workbook.IsDigitallySigned) + { + Console.WriteLine("The workbook is digitally signed. Proceeding to save a copy."); + } + else + { + Console.WriteLine("Warning: The workbook does not contain a digital signature."); + } + + // Save the workbook to a new location. + // The digital signature is preserved automatically during the save operation. + workbook.Save(destinationPath); + + Console.WriteLine($"Workbook successfully saved to: {destinationPath}"); + } +} \ No newline at end of file diff --git a/macro-project/save-the-workbook-as-a-macroenabled-xlsm-file-to-the-specified-location.cs b/macro-project/save-the-workbook-as-a-macroenabled-xlsm-file-to-the-specified-location.cs new file mode 100644 index 0000000000..231da7012c --- /dev/null +++ b/macro-project/save-the-workbook-as-a-macroenabled-xlsm-file-to-the-specified-location.cs @@ -0,0 +1,28 @@ +using System; +using Aspose.Cells; + +namespace AsposeCellsMacroSaveDemo +{ + class Program + { + static void Main() + { + // Create a new workbook (default is a macro‑enabled workbook when saved as Xlsm) + Workbook workbook = new Workbook(); + + // Add some sample data to the first worksheet + Worksheet sheet = workbook.Worksheets[0]; + sheet.Cells["A1"].PutValue("Macro‑Enabled"); + sheet.Cells["B1"].PutValue(DateTime.Now); + + // Specify the output path + string outputPath = "MacroEnabledWorkbook.xlsm"; + + // Save the workbook as a macro‑enabled XLSM file + // Uses the Save(string, SaveFormat) overload as defined in the Aspose.Cells API + workbook.Save(outputPath, SaveFormat.Xlsm); + + Console.WriteLine($"Workbook saved successfully to '{outputPath}'."); + } + } +} \ No newline at end of file diff --git a/macro-project/serialize-the-vba-project-structure-including-module-names-and-code-snippets-into-a-json-report-file.cs b/macro-project/serialize-the-vba-project-structure-including-module-names-and-code-snippets-into-a-json-report-file.cs new file mode 100644 index 0000000000..f3bd072714 --- /dev/null +++ b/macro-project/serialize-the-vba-project-structure-including-module-names-and-code-snippets-into-a-json-report-file.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace VbaProjectJsonReport +{ + // Represents a simplified VBA module information for JSON serialization + public class VbaModuleInfo + { + public string Name { get; set; } + public string Type { get; set; } + public string Codes { get; set; } + } + + // Represents the VBA project report structure + public class VbaProjectReport + { + public string ProjectName { get; set; } + public List Modules { get; set; } = new List(); + } + + class Program + { + static void Main(string[] args) + { + // Path to the input workbook (macro-enabled). Adjust as needed. + string inputPath = "input.xlsm"; + + // Load the workbook; if it does not exist, create a new macro-enabled workbook and add a sample module. + Workbook workbook; + if (File.Exists(inputPath)) + { + workbook = new Workbook(inputPath); + } + else + { + workbook = new Workbook(); + // Ensure the workbook is saved as macro-enabled later. + // Add a sample VBA module so that the report contains data. + int idx = workbook.VbaProject.Modules.Add(VbaModuleType.Class, "SampleModule"); + VbaModule sampleModule = workbook.VbaProject.Modules[idx]; + sampleModule.Codes = "Sub HelloWorld()\r\n MsgBox \"Hello from VBA!\"\r\nEnd Sub"; + } + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Build the report object + VbaProjectReport report = new VbaProjectReport + { + ProjectName = vbaProject.Name + }; + + // Iterate through all modules and collect their details + foreach (VbaModule module in vbaProject.Modules) + { + VbaModuleInfo info = new VbaModuleInfo + { + Name = module.Name, + Type = module.Type.ToString(), + Codes = module.Codes ?? string.Empty + }; + report.Modules.Add(info); + } + + // Serialize the report to JSON with indentation for readability + JsonSerializerOptions options = new JsonSerializerOptions + { + WriteIndented = true + }; + string json = JsonSerializer.Serialize(report, options); + + // Define the output JSON file path + string outputPath = "VbaProjectReport.json"; + + // Write the JSON content to the file + File.WriteAllText(outputPath, json); + + Console.WriteLine($"VBA project report has been generated at: {Path.GetFullPath(outputPath)}"); + + // Save the workbook as macro-enabled if it was newly created + if (!File.Exists(inputPath)) + { + workbook.Save("GeneratedWorkbook.xlsm", SaveFormat.Xlsm); + } + } + } +} \ No newline at end of file diff --git a/macro-project/set-the-buttons-macroname-property-to-reference-the-newly-added-macro.cs b/macro-project/set-the-buttons-macroname-property-to-reference-the-newly-added-macro.cs new file mode 100644 index 0000000000..5ebfbf54de --- /dev/null +++ b/macro-project/set-the-buttons-macroname-property-to-reference-the-newly-added-macro.cs @@ -0,0 +1,40 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Drawing; +using Aspose.Cells.Vba; + +namespace AsposeCellsMacroButtonDemo +{ + public class Program + { + public static void Main() + { + // Create a new workbook and get the first worksheet + Workbook workbook = new Workbook(); + Worksheet sheet = workbook.Worksheets[0]; + + // Enable macros in the workbook + workbook.Settings.EnableMacros = true; + + // Add a VBA module to the workbook and insert a simple macro + int moduleIndex = workbook.VbaProject.Modules.Add(sheet); + VbaModule module = workbook.VbaProject.Modules[moduleIndex]; + module.Name = "Module1"; + module.Codes = @" +Sub MyMacro() + MsgBox ""Hello from MyMacro!"" +End Sub"; + + // Add a Forms button to the worksheet + // Parameters: topRow, top (pixel offset), leftColumn, left (pixel offset), height (pixels), width (pixels) + Button button = sheet.Shapes.AddButton(1, 0, 1, 0, 30, 100); + button.Text = "Run Macro"; + + // Associate the button with the newly added macro + button.MacroName = "MyMacro"; + + // Save the workbook as a macro‑enabled file + workbook.Save("ButtonWithMacro.xlsm"); + } + } +} \ No newline at end of file diff --git a/macro-project/sign-the-vba-project-using-a-certificate-retrieved-from-windows-certificate-store-by-thumbprint.cs b/macro-project/sign-the-vba-project-using-a-certificate-retrieved-from-windows-certificate-store-by-thumbprint.cs new file mode 100644 index 0000000000..c3ef9a0bc9 --- /dev/null +++ b/macro-project/sign-the-vba-project-using-a-certificate-retrieved-from-windows-certificate-store-by-thumbprint.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaSigning +{ + public class SignVbaProjectWithStoreCertificate + { + public static void Run() + { + try + { + // Path to the workbook that contains a VBA project (must be macro‑enabled) + string workbookPath = "InputWorkbook.xlsm"; + + // Verify the input file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Input workbook not found: {workbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Ensure the workbook has a VBA project; if not, create one by saving as .xlsm and reloading + if (workbook.VbaProject == null) + { + string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".xlsm"); + workbook.Save(tempPath, SaveFormat.Xlsm); + workbook = new Workbook(tempPath); + File.Delete(tempPath); + } + + // Retrieve the certificate from the Windows certificate store by thumbprint + string thumbprint = "YOUR_CERTIFICATE_THUMBPRINT".Replace(" ", "").ToUpperInvariant(); // replace with actual thumbprint + X509Certificate2 certificate = null; + + using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadOnly); + var certCollection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); + if (certCollection.Count > 0) + { + certificate = certCollection[0]; + } + } + + if (certificate == null) + { + Console.WriteLine("Certificate with the specified thumbprint was not found in the store."); + return; + } + + // Create a digital signature using the retrieved certificate + DigitalSignature digitalSignature = new DigitalSignature( + certificate, + "VBA Project Signature", + DateTime.Now); + + // Sign the VBA project + VbaProject vbaProject = workbook.VbaProject; + vbaProject.Sign(digitalSignature); + + // Save the signed workbook + string signedWorkbookPath = "SignedWorkbook.xlsm"; + workbook.Save(signedWorkbookPath, SaveFormat.Xlsm); + + // Optional: verify the signature + Workbook verifyWorkbook = new Workbook(signedWorkbookPath); + Console.WriteLine("VBA Project IsSigned: " + verifyWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + verifyWorkbook.VbaProject.IsValidSigned); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + } + + public class Program + { + public static void Main(string[] args) + { + SignVbaProjectWithStoreCertificate.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/sign-the-vba-project-using-a-pfx-certificate-file-protected-by-a-strong-password.cs b/macro-project/sign-the-vba-project-using-a-pfx-certificate-file-protected-by-a-strong-password.cs new file mode 100644 index 0000000000..6723d8f65d --- /dev/null +++ b/macro-project/sign-the-vba-project-using-a-pfx-certificate-file-protected-by-a-strong-password.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaSigningDemo +{ + public class VbaProjectSigner + { + public static void Main() + { + Run(); + } + + public static void Run() + { + try + { + // Paths for input workbook, output workbook and certificate + string inputPath = "MacroWorkbook.xlsm"; + string outputPath = "MacroWorkbook_Signed.xlsm"; + string certificatePath = "MyCertificate.pfx"; + string certificatePassword = "StrongPassword123!"; + + // Verify that required files exist + if (!File.Exists(inputPath)) + { + Console.WriteLine($"Input workbook not found: {inputPath}"); + return; + } + + if (!File.Exists(certificatePath)) + { + Console.WriteLine($"Certificate file not found: {certificatePath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Load the certificate (includes private key) + X509Certificate2 certificate = new X509Certificate2( + File.ReadAllBytes(certificatePath), certificatePassword); + + // Create a digital signature instance + DigitalSignature digitalSignature = new DigitalSignature( + certificate, // certificate with private key + "Signed by Aspose.Cells", // optional comment + DateTime.Now); // signing time + + // Sign the VBA project + vbaProject.Sign(digitalSignature); + + // Save the signed workbook + workbook.Save(outputPath, SaveFormat.Xlsm); + + // Verify the signature + Workbook verifyWorkbook = new Workbook(outputPath); + Console.WriteLine("VBA Project Signed: " + verifyWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Signature Valid: " + verifyWorkbook.VbaProject.IsValidSigned); + } + catch (Exception ex) + { + Console.WriteLine("An error occurred: " + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/macro-project/sign-the-vba-project-with-a-certificate-loaded-from-a-pfx-file-and-password.cs b/macro-project/sign-the-vba-project-with-a-certificate-loaded-from-a-pfx-file-and-password.cs new file mode 100644 index 0000000000..443c890ca5 --- /dev/null +++ b/macro-project/sign-the-vba-project-with-a-certificate-loaded-from-a-pfx-file-and-password.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaSigningDemo +{ + public class VbaProjectSigner + { + public static void Run() + { + try + { + // Path to the macro-enabled workbook (XLSM) that contains a VBA project + string workbookPath = "InputWorkbook.xlsm"; + + // Verify workbook file exists + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Ensure the workbook actually contains a VBA project + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Path to the signing certificate (PFX) and its password + string certPath = "MyCertificate.pfx"; + string certPassword = "pfxPassword"; + + // Verify certificate file exists + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load the signing certificate + X509Certificate2 certificate = new X509Certificate2(certPath, certPassword); + + // Create a DigitalSignature instance using the certificate + DigitalSignature digitalSignature = new DigitalSignature( + certificate, // certificate with private key + "Signed by Aspose.Cells", // optional comment + DateTime.Now); // signing time + + // Sign the VBA project + vbaProject.Sign(digitalSignature); + + // Save the signed workbook as a macro-enabled file + string signedWorkbookPath = "SignedWorkbook.xlsm"; + workbook.Save(signedWorkbookPath, SaveFormat.Xlsm); + + // Optional: Verify the signature after saving + Workbook verifyWorkbook = new Workbook(signedWorkbookPath); + Console.WriteLine("VBA Project Signed: " + verifyWorkbook.VbaProject.IsSigned); + Console.WriteLine("Signature Valid: " + verifyWorkbook.VbaProject.IsValidSigned); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + } + + // Entry point for the application + public class Program + { + public static void Main(string[] args) + { + VbaProjectSigner.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/sign-the-vba-project-with-a-certificate-stored-in-the-windows-certificate-store-using-its-thumbprint.cs b/macro-project/sign-the-vba-project-with-a-certificate-stored-in-the-windows-certificate-store-using-its-thumbprint.cs new file mode 100644 index 0000000000..65790424bc --- /dev/null +++ b/macro-project/sign-the-vba-project-with-a-certificate-stored-in-the-windows-certificate-store-using-its-thumbprint.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsVbaSigning +{ + class Program + { + static void Main() + { + // Path to the macro-enabled workbook that contains a VBA project + string inputPath = "MacroWorkbook.xlsm"; + + // Load the workbook (lifecycle rule: load) + Workbook workbook = new Workbook(inputPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Thumbprint of the certificate stored in the Windows certificate store + string certThumbprint = "YOUR_CERTIFICATE_THUMBPRINT".Replace(" ", string.Empty).ToUpperInvariant(); + + // Open the personal (My) store of the current user + using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadOnly); + + // Find the certificate by thumbprint + X509Certificate2Collection found = store.Certificates.Find( + X509FindType.FindByThumbprint, + certThumbprint, + validOnly: false); + + if (found.Count == 0) + { + Console.WriteLine($"Certificate with thumbprint {certThumbprint} not found in the store."); + return; + } + + X509Certificate2 certificate = found[0]; + + // Create a digital signature using the certificate + DigitalSignature digitalSignature = new DigitalSignature( + certificate, + "Signed by Aspose.Cells VBA signing routine", + DateTime.Now); + + // Sign the VBA project (method rule: Sign) + vbaProject.Sign(digitalSignature); + } + + // Save the signed workbook (lifecycle rule: save) + string outputPath = "SignedMacroWorkbook.xlsm"; + workbook.Save(outputPath, SaveFormat.Xlsm); + + // Verify signing status + Workbook verifyWb = new Workbook(outputPath); + Console.WriteLine("VBA Project IsSigned: " + verifyWb.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + verifyWb.VbaProject.IsValidSigned); + } + } +} \ No newline at end of file diff --git a/macro-project/sign-workbook-using-certificate-from-windows-store-selected-by-subject-name-for-code-signing.cs b/macro-project/sign-workbook-using-certificate-from-windows-store-selected-by-subject-name-for-code-signing.cs new file mode 100644 index 0000000000..0f8f7854f6 --- /dev/null +++ b/macro-project/sign-workbook-using-certificate-from-windows-store-selected-by-subject-name-for-code-signing.cs @@ -0,0 +1,60 @@ +using System; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsDigitalSignatureDemo +{ + class Program + { + static void Main() + { + // Define the subject name to search for in the Windows certificate store + const string certificateSubjectName = "CN=MyCodeSigningCert"; + + // Open the Current User's Personal (My) certificate store + X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); + store.Open(OpenFlags.ReadOnly); + + // Find a certificate that matches the subject name and has a private key (required for signing) + X509Certificate2 signingCertificate = store.Certificates + .Cast() + .FirstOrDefault(cert => + cert.Subject.Equals(certificateSubjectName, StringComparison.OrdinalIgnoreCase) && + cert.HasPrivateKey); + + store.Close(); + + if (signingCertificate == null) + { + Console.WriteLine("Certificate with subject '{0}' not found in the store.", certificateSubjectName); + return; + } + + // Create a new workbook (or load an existing one) + Workbook workbook = new Workbook(); // creates a new workbook + // Example: add some content + workbook.Worksheets[0].Cells["A1"].PutValue("Digitally Signed Workbook"); + + // Create a digital signature using the certificate, a comment, and the current UTC time + DigitalSignature signature = new DigitalSignature( + signingCertificate, + "Code signing of workbook", + DateTime.UtcNow); + + // Add the signature to a collection + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + signatures.Add(signature); + + // Apply the digital signature to the workbook + workbook.SetDigitalSignature(signatures); + + // Save the signed workbook + string outputPath = "SignedWorkbook.xlsx"; + workbook.Save(outputPath); + + Console.WriteLine("Workbook signed and saved to: " + outputPath); + } + } +} \ No newline at end of file diff --git a/macro-project/skip-protecting-workbooks-that-are-already-secured-by-using-isprotected-in-a-conditional-statement.cs b/macro-project/skip-protecting-workbooks-that-are-already-secured-by-using-isprotected-in-a-conditional-statement.cs new file mode 100644 index 0000000000..8cedd952f6 --- /dev/null +++ b/macro-project/skip-protecting-workbooks-that-are-already-secured-by-using-isprotected-in-a-conditional-statement.cs @@ -0,0 +1,37 @@ +using System; +using Aspose.Cells; + +namespace AsposeCellsProtectionDemo +{ + class Program + { + static void Main(string[] args) + { + // Path to the workbook to be processed + string inputPath = "input.xlsx"; + string outputPath = "output.xlsx"; + string password = "mySecret"; + + // Load the workbook + Workbook workbook = new Workbook(inputPath); + + // Check if the workbook is already protected (structure or window) + // WorkbookSettings.IsProtected indicates protection status + if (!workbook.Settings.IsProtected) + { + // Workbook is not protected, apply protection with a password + workbook.Protect(ProtectionType.All, password); + Console.WriteLine("Workbook was not protected. Protection applied."); + } + else + { + // Workbook is already protected; skip protecting again + Console.WriteLine("Workbook is already protected. Skipping protection."); + } + + // Save the workbook (protected or unchanged) + workbook.Save(outputPath, SaveFormat.Xlsx); + Console.WriteLine($"Workbook saved to '{outputPath}'."); + } + } +} \ No newline at end of file diff --git a/macro-project/transfer-a-userform-called-inputform-between-two-workbooks-while-preserving-its-controls-and-code.cs b/macro-project/transfer-a-userform-called-inputform-between-two-workbooks-while-preserving-its-controls-and-code.cs new file mode 100644 index 0000000000..d11a5b2c00 --- /dev/null +++ b/macro-project/transfer-a-userform-called-inputform-between-two-workbooks-while-preserving-its-controls-and-code.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class TransferUserForm +{ + static void Main() + { + try + { + const string sourcePath = "SourceWithForm.xlsm"; + const string destPath = "DestinationWithForm.xlsm"; + + // Verify source file exists to avoid FileNotFoundException + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: {sourcePath}"); + return; + } + + // Load the source workbook that contains the UserForm named "InputForm" + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Create an empty destination workbook + Workbook destinationWorkbook = new Workbook(); + + // Copy the entire VBA project (modules, userforms, references, etc.) from source to destination + destinationWorkbook.VbaProject.Copy(sourceWorkbook.VbaProject); + + // Ensure that any external VBA references are also copied (optional, but safe) + destinationWorkbook.VbaProject.References.Copy(sourceWorkbook.VbaProject.References); + + // Save the destination workbook as a macro‑enabled file to preserve the UserForm + destinationWorkbook.Save(destPath, SaveFormat.Xlsm); + + Console.WriteLine($"VBA project successfully transferred to {destPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/macro-project/use-a-trycatch-block-to-handle-exceptions-when-exporting-a-certificate-from-an-unsigned-vba-project.cs b/macro-project/use-a-trycatch-block-to-handle-exceptions-when-exporting-a-certificate-from-an-unsigned-vba-project.cs new file mode 100644 index 0000000000..b22d3d12a9 --- /dev/null +++ b/macro-project/use-a-trycatch-block-to-handle-exceptions-when-exporting-a-certificate-from-an-unsigned-vba-project.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ExportVbaCertificate +{ + public static void Run() + { + try + { + // Path to the workbook that may contain a signed VBA project + string workbookPath = "UnsignedWorkbook.xlsm"; + + // Verify that the file exists before attempting to load it + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Workbook file not found: {workbookPath}"); + return; + } + + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Check if the VBA project is signed + if (vbaProject.IsSigned) + { + // Retrieve the raw certificate data + byte[] certData = vbaProject.CertRawData; + + // Ensure data exists before exporting + if (certData != null && certData.Length > 0) + { + // Export the certificate to a .cer file + string outputPath = "ExportedVbaCertificate.cer"; + File.WriteAllBytes(outputPath, certData); + Console.WriteLine($"Certificate exported successfully to {outputPath}."); + } + else + { + Console.WriteLine("Certificate data is empty."); + } + } + else + { + Console.WriteLine("VBA project is not signed. No certificate to export."); + } + } + catch (CellsException ex) + { + // Handle Aspose.Cells specific exceptions + Console.WriteLine($"Aspose.Cells error: {ex.Message}"); + Console.WriteLine($"Error code: {ex.Code}"); + } + catch (Exception ex) + { + // Handle any other unexpected exceptions + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + } +} + +class Program +{ + static void Main(string[] args) + { + ExportVbaCertificate.Run(); + } +} \ No newline at end of file diff --git a/macro-project/use-asynchronous-tasks-to-sign-multiple-workbooks-concurrently-improving-processing-throughput-significantly.cs b/macro-project/use-asynchronous-tasks-to-sign-multiple-workbooks-concurrently-improving-processing-throughput-significantly.cs new file mode 100644 index 0000000000..fc1c25141e --- /dev/null +++ b/macro-project/use-asynchronous-tasks-to-sign-multiple-workbooks-concurrently-improving-processing-throughput-significantly.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsConcurrentSigning +{ + class Program + { + // Asynchronously signs a single workbook and saves the signed copy. + private static async Task SignWorkbookAsync(string inputPath, string outputPath, X509Certificate2 certificate) + { + try + { + if (!File.Exists(inputPath)) + throw new FileNotFoundException($"Input workbook not found: {inputPath}"); + + // Load the workbook. + using (Workbook workbook = new Workbook(inputPath)) + { + // Create a digital signature. + DigitalSignature signature = new DigitalSignature(certificate, "Concurrent Signature", DateTime.Now); + + // Add the signature to a collection and attach it to the workbook. + DigitalSignatureCollection signatures = new DigitalSignatureCollection { signature }; + workbook.AddDigitalSignature(signatures); + + // Save the signed workbook. + workbook.Save(outputPath); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error signing workbook '{inputPath}': {ex.Message}"); + } + + // Simulate asynchronous work (optional). + await Task.CompletedTask; + } + + static async Task Main(string[] args) + { + try + { + // Paths of workbooks to be signed. + List inputFiles = new List + { + "Workbook1.xlsx", + "Workbook2.xlsx", + "Workbook3.xlsx" + }; + + // Corresponding output paths for signed workbooks. + List outputFiles = new List + { + "Workbook1_Signed.xlsx", + "Workbook2_Signed.xlsx", + "Workbook3_Signed.xlsx" + }; + + // Verify certificate file exists before loading. + string certPath = "certificate.pfx"; + string certPassword = "password"; + + if (!File.Exists(certPath)) + throw new FileNotFoundException($"Certificate file not found: {certPath}"); + + // Load the signing certificate. + X509Certificate2 cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.MachineKeySet); + + // Create a list to hold signing tasks. + List signingTasks = new List(); + + // Launch signing tasks concurrently. + for (int i = 0; i < inputFiles.Count; i++) + { + string input = inputFiles[i]; + string output = outputFiles[i]; + signingTasks.Add(SignWorkbookAsync(input, output, cert)); + } + + // Wait for all signing operations to complete. + await Task.WhenAll(signingTasks); + + Console.WriteLine("All workbooks have been signed successfully."); + } + catch (Exception ex) + { + Console.WriteLine($"Fatal error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/use-reflection-to-enumerate-all-vba-project-references-and-output-their-names-and-versions.cs b/macro-project/use-reflection-to-enumerate-all-vba-project-references-and-output-their-names-and-versions.cs new file mode 100644 index 0000000000..a55e5c8aca --- /dev/null +++ b/macro-project/use-reflection-to-enumerate-all-vba-project-references-and-output-their-names-and-versions.cs @@ -0,0 +1,53 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; +using System.Reflection; + +class EnumerateVbaReferences +{ + static void Main() + { + // Load a macro-enabled workbook (replace with your file path) + Workbook workbook = new Workbook("input.xlsm"); + + // Get the VBA project via reflection + PropertyInfo vbaProjectProp = typeof(Workbook).GetProperty("VbaProject"); + VbaProject vbaProject = (VbaProject)vbaProjectProp.GetValue(workbook); + + if (vbaProject == null) + { + Console.WriteLine("The workbook does not contain a VBA project."); + return; + } + + // Obtain the References collection using reflection + PropertyInfo referencesProp = typeof(VbaProject).GetProperty("References"); + VbaProjectReferenceCollection references = (VbaProjectReferenceCollection)referencesProp.GetValue(vbaProject); + + // Prepare reflection objects for the properties we need + PropertyInfo nameProp = typeof(VbaProjectReference).GetProperty("Name"); + PropertyInfo libidProp = typeof(VbaProjectReference).GetProperty("Libid"); + + // Enumerate all references and output their name and version (extracted from Libid) + for (int i = 0; i < references.Count; i++) + { + VbaProjectReference reference = references[i]; + string name = (string)nameProp.GetValue(reference); + string libid = (string)libidProp.GetValue(reference); + + // Attempt to extract version information from the Libid string (if present) + string version = "Unknown"; + if (!string.IsNullOrEmpty(libid)) + { + // Libid format often contains version after the second '#' + string[] parts = libid.Split('#'); + if (parts.Length > 2) + { + version = parts[2]; + } + } + + Console.WriteLine($"Reference {i + 1}: Name = {name}, Version = {version}"); + } + } +} \ No newline at end of file diff --git a/macro-project/validate-that-adding-a-library-reference-throws-an-exception-when-the-library-is-not-registered-on-the-host.cs b/macro-project/validate-that-adding-a-library-reference-throws-an-exception-when-the-library-is-not-registered-on-the-host.cs new file mode 100644 index 0000000000..62158a3f51 --- /dev/null +++ b/macro-project/validate-that-adding-a-library-reference-throws-an-exception-when-the-library-is-not-registered-on-the-host.cs @@ -0,0 +1,46 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ValidateUnregisteredLibraryReference +{ + static void Main() + { + // Create a new workbook + Workbook workbook = new Workbook(); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Define a library name and libid that are not registered on the host + string libName = "NonExistentLib"; + string libId = "*\\G{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}#0.0#0#C:\\InvalidPath\\nonexistent.tlb#Invalid"; + + bool exceptionThrown = false; + + try + { + // Attempt to add the unregistered reference; this should raise an exception + vbaProject.References.AddRegisteredReference(libName, libId); + } + catch (Exception ex) + { + // Expected exception caught + exceptionThrown = true; + Console.WriteLine("Expected exception caught: " + ex.Message); + } + + // Verify that the exception was indeed thrown + if (!exceptionThrown) + { + Console.WriteLine("Error: No exception was thrown for an unregistered library reference."); + } + else + { + Console.WriteLine("Validation succeeded: exception was thrown as expected."); + } + + // Save the workbook (optional, will contain no references) + workbook.Save("ValidationResult.xlsm"); + } +} \ No newline at end of file diff --git a/macro-project/validate-that-each-added-module-contains-a-sub-main-entry-point-before-committing-workbook-changes.cs b/macro-project/validate-that-each-added-module-contains-a-sub-main-entry-point-before-committing-workbook-changes.cs new file mode 100644 index 0000000000..deb1507eef --- /dev/null +++ b/macro-project/validate-that-each-added-module-contains-a-sub-main-entry-point-before-committing-workbook-changes.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaValidation +{ + public class Program + { + public static void Main() + { + try + { + // Create a new workbook (macro‑enabled format will be used on save) + Workbook workbook = new Workbook(); + + // Access the VBA project + VbaProject vbaProject = workbook.VbaProject; + + // Add two class modules + int idx1 = vbaProject.Modules.Add(VbaModuleType.Class, "ModuleOne"); + VbaModule moduleOne = vbaProject.Modules[idx1]; + moduleOne.Codes = @"Sub Main() + MsgBox ""Hello from ModuleOne!"" +End Sub"; + + int idx2 = vbaProject.Modules.Add(VbaModuleType.Class, "ModuleTwo"); + VbaModule moduleTwo = vbaProject.Modules[idx2]; + // This module intentionally lacks Sub Main to demonstrate validation + moduleTwo.Codes = @"Sub Helper() + MsgBox ""Helper routine"" +End Sub"; + + // Validate that each *class* module contains a Sub Main entry point + foreach (VbaModule module in vbaProject.Modules) + { + // Skip non‑class modules such as ThisWorkbook or Sheet modules + if (module.Type != VbaModuleType.Class) + continue; + + bool hasMain = Regex.IsMatch( + module.Codes ?? string.Empty, + @"^\s*Sub\s+Main\s*\(\s*\)", + RegexOptions.IgnoreCase | RegexOptions.Multiline); + + if (!hasMain) + { + throw new InvalidOperationException( + $"VBA module \"{module.Name}\" does not contain a Sub Main entry point."); + } + } + + // All modules passed validation – save the workbook as a macro‑enabled file + string outputPath = "ValidatedWorkbook.xlsm"; + + // Ensure the directory exists before saving + string outputDir = Path.GetDirectoryName(Path.GetFullPath(outputPath)); + if (!Directory.Exists(outputDir)) + { + Directory.CreateDirectory(outputDir); + } + + workbook.Save(outputPath, SaveFormat.Xlsm); + Console.WriteLine($"Workbook saved successfully to \"{outputPath}\"."); + } + catch (Exception ex) + { + // Log any errors without crashing the application + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/validate-that-the-exported-certificate-stream-length-matches-the-original-file-size.cs b/macro-project/validate-that-the-exported-certificate-stream-length-matches-the-original-file-size.cs new file mode 100644 index 0000000000..8fa22aaf4e --- /dev/null +++ b/macro-project/validate-that-the-exported-certificate-stream-length-matches-the-original-file-size.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsCertificateValidation +{ + public class CertificateStreamValidator + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + } + + public static void Run() + { + try + { + // Path to the original certificate file (e.g., .pfx) + string certificatePath = "test.pfx"; + + // Ensure the certificate file exists + if (!File.Exists(certificatePath)) + { + Console.WriteLine($"Certificate file not found: {certificatePath}"); + return; + } + + // Read the original certificate file into a byte array + byte[] originalCertificateBytes = File.ReadAllBytes(certificatePath); + long originalFileSize = originalCertificateBytes.Length; + + // Export the certificate to a memory stream (simulating an export operation) + using (MemoryStream exportedStream = new MemoryStream()) + { + exportedStream.Write(originalCertificateBytes, 0, originalCertificateBytes.Length); + exportedStream.Flush(); + + long exportedLength = exportedStream.Length; + bool isLengthMatch = exportedLength == originalFileSize; + + Console.WriteLine($"Original file size: {originalFileSize} bytes"); + Console.WriteLine($"Exported stream length: {exportedLength} bytes"); + Console.WriteLine($"Length match: {isLengthMatch}"); + } + + // Create a new workbook and add a digital signature using the certificate data + Workbook workbook = new Workbook(); + + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + DigitalSignature signature = new DigitalSignature( + originalCertificateBytes, // certificate data + "certificatePassword", // password for the certificate (if any) + "Demo Signature", // comments (used as description) + DateTime.Now); // signing time + + signatures.Add(signature); + workbook.SetDigitalSignature(signatures); + + // Save the signed workbook to a file + string signedWorkbookPath = "signed_workbook.xlsx"; + workbook.Save(signedWorkbookPath, SaveFormat.Xlsx); + + // Ensure the signed workbook was saved before loading + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"Signed workbook not found: {signedWorkbookPath}"); + return; + } + + // Load the signed workbook and retrieve the signature to verify the certificate length again + Workbook loadedWorkbook = new Workbook(signedWorkbookPath); + DigitalSignatureCollection loadedSignatures = loadedWorkbook.GetDigitalSignature(); + + foreach (DigitalSignature loadedSignature in loadedSignatures) + { + // Output signature information (comments and signing time) + Console.WriteLine("Signature comments: " + loadedSignature.Comments); + Console.WriteLine("Signature signing time: " + loadedSignature.SignTime); + Console.WriteLine("Assumed certificate length matches original: " + + (originalCertificateBytes.Length == originalFileSize)); + } + } + catch (Exception ex) + { + // Catch any runtime errors within Run + Console.WriteLine($"Runtime error: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/macro-project/validate-that-the-vba-project-password-meets-minimum-length-requirements-before-invoking-the-protect-method.cs b/macro-project/validate-that-the-vba-project-password-meets-minimum-length-requirements-before-invoking-the-protect-method.cs new file mode 100644 index 0000000000..7e6e06bef0 --- /dev/null +++ b/macro-project/validate-that-the-vba-project-password-meets-minimum-length-requirements-before-invoking-the-protect-method.cs @@ -0,0 +1,40 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class VbaProjectPasswordValidationDemo +{ + static void Main() + { + // Create a new workbook (lifecycle rule) + Workbook workbook = new Workbook(); + + // Ensure a VBA project exists by adding a worksheet + workbook.Worksheets.Add(); + + // Define the password to protect the VBA project + string password = "MySecurePwd123"; + + // Minimum password length requirement + const int MinPasswordLength = 8; + + // Validate password length before protecting + if (string.IsNullOrEmpty(password) || password.Length < MinPasswordLength) + { + Console.WriteLine($"Password must be at least {MinPasswordLength} characters long."); + } + else + { + // Protect the VBA project (lock for viewing set to true) + workbook.VbaProject.Protect(true, password); + Console.WriteLine("VBA project protected successfully."); + + // Optional: verify that the password works using ValidatePassword + bool isValid = workbook.VbaProject.ValidatePassword(password); + Console.WriteLine($"Password validation result after protection: {isValid}"); + } + + // Save the workbook (lifecycle rule) + workbook.Save("ProtectedVbaProject.xlsm", SaveFormat.Xlsm); + } +} \ No newline at end of file diff --git a/macro-project/validate-the-digital-signature-of-a-vba-project-after-adding-a-new-macro-to-ensure-the-signature-reflects-changes.cs b/macro-project/validate-the-digital-signature-of-a-vba-project-after-adding-a-new-macro-to-ensure-the-signature-reflects-changes.cs new file mode 100644 index 0000000000..50b73aa447 --- /dev/null +++ b/macro-project/validate-the-digital-signature-of-a-vba-project-after-adding-a-new-macro-to-ensure-the-signature-reflects-changes.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.Vba; +using Aspose.Cells.DigitalSignatures; + +class ValidateVbaSignatureAfterMacro +{ + static void Main() + { + // Create a new workbook and save it as a macro‑enabled file to ensure a VBA project exists + Workbook workbook = new Workbook(); + string tempFile = "temp.xlsm"; + workbook.Save(tempFile, SaveFormat.Xlsm); + + // Reload the workbook so that the VBA project is initialized + workbook = new Workbook(tempFile); + + // Add a new VBA module (class type) and insert macro code + int moduleIndex = workbook.VbaProject.Modules.Add(VbaModuleType.Class, "NewModule"); + VbaModule module = workbook.VbaProject.Modules[moduleIndex]; + module.Codes = "Sub NewMacro()\r\n MsgBox \"Hello from new macro!\"\r\nEnd Sub"; + + // Load a signing certificate (replace with your own certificate path and password) + X509Certificate2 certificate = new X509Certificate2("MyCertificate.pfx", "certPassword"); + + // Create a digital signature for the VBA project + DigitalSignature vbaSignature = new DigitalSignature(certificate, "VBA Project Signature", DateTime.Now); + + // Sign the VBA project with the created signature + workbook.VbaProject.Sign(vbaSignature); + + // Save the workbook to a memory stream + using (MemoryStream ms = new MemoryStream()) + { + workbook.Save(ms, SaveFormat.Xlsm); + + // Reload the workbook from the stream to verify the signature + Workbook reloadedWorkbook = new Workbook(ms); + + // Output signature validation results + Console.WriteLine("VBA Project IsSigned: " + reloadedWorkbook.VbaProject.IsSigned); + Console.WriteLine("VBA Project IsValidSigned: " + reloadedWorkbook.VbaProject.IsValidSigned); + } + + // Clean up the temporary file + if (File.Exists(tempFile)) + { + File.Delete(tempFile); + } + } +} \ No newline at end of file diff --git a/macro-project/validate-the-digital-signature-of-a-vba-project-after-copying-it-to-ensure-integrity-remains-intact.cs b/macro-project/validate-the-digital-signature-of-a-vba-project-after-copying-it-to-ensure-integrity-remains-intact.cs new file mode 100644 index 0000000000..cefa8f9855 --- /dev/null +++ b/macro-project/validate-the-digital-signature-of-a-vba-project-after-copying-it-to-ensure-integrity-remains-intact.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class VbaProjectSignatureValidationAfterCopy + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine("Error: " + ex.Message); + } + } + + public static void Run() + { + const string sourcePath = "SignedSource.xlsm"; + + // Verify source file exists + if (!File.Exists(sourcePath)) + { + Console.WriteLine($"Source file not found: {sourcePath}"); + return; + } + + // Load the source workbook that already contains a signed VBA project + Workbook sourceWorkbook = new Workbook(sourcePath); + + // Verify that the source VBA project is signed and the signature is valid + Console.WriteLine("Source - IsSigned: " + sourceWorkbook.VbaProject.IsSigned); + Console.WriteLine("Source - IsValidSigned: " + sourceWorkbook.VbaProject.IsValidSigned); + + // Create a new empty macro-enabled workbook + Workbook destWorkbook = new Workbook(); + using (MemoryStream tempStream = new MemoryStream()) + { + destWorkbook.Save(tempStream, SaveFormat.Xlsm); + tempStream.Position = 0; + destWorkbook = new Workbook(tempStream); + } + + // Copy the VBA project from the source workbook to the destination workbook + destWorkbook.VbaProject.Copy(sourceWorkbook.VbaProject); + + // Save the destination workbook to a memory stream and reload to simulate a fresh load + using (MemoryStream copiedStream = new MemoryStream()) + { + destWorkbook.Save(copiedStream, SaveFormat.Xlsm); + copiedStream.Position = 0; + + Workbook reloadedWorkbook = new Workbook(copiedStream); + + // Validate the VBA project's signature in the reloaded workbook + Console.WriteLine("After Copy - IsSigned: " + reloadedWorkbook.VbaProject.IsSigned); + Console.WriteLine("After Copy - IsValidSigned: " + reloadedWorkbook.VbaProject.IsValidSigned); + } + } + } +} \ No newline at end of file diff --git a/macro-project/validate-the-digital-signature-of-the-vba-project-and-report-any-verification-errors.cs b/macro-project/validate-the-digital-signature-of-the-vba-project-and-report-any-verification-errors.cs new file mode 100644 index 0000000000..b19fe05424 --- /dev/null +++ b/macro-project/validate-the-digital-signature-of-the-vba-project-and-report-any-verification-errors.cs @@ -0,0 +1,32 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ValidateVbaSignature +{ + static void Main() + { + // Load the workbook that contains a VBA project + Workbook workbook = new Workbook("sample.xlsm"); + + // Determine whether the VBA project is signed + if (workbook.VbaProject.IsSigned) + { + Console.WriteLine("VBA project is signed."); + + // Verify if the signature is valid + bool isValid = workbook.VbaProject.IsValidSigned; + Console.WriteLine("Signature valid: " + isValid); + + // Report any verification errors + if (!isValid) + { + Console.WriteLine("Error: VBA project signature verification failed."); + } + } + else + { + Console.WriteLine("VBA project is not signed."); + } + } +} \ No newline at end of file diff --git a/macro-project/validate-the-vba-projects-digital-signature-using-workbookvbaprojectvalidatesignature-method-and-capture-result.cs b/macro-project/validate-the-vba-projects-digital-signature-using-workbookvbaprojectvalidatesignature-method-and-capture-result.cs new file mode 100644 index 0000000000..4a9ab33df6 --- /dev/null +++ b/macro-project/validate-the-vba-projects-digital-signature-using-workbookvbaprojectvalidatesignature-method-and-capture-result.cs @@ -0,0 +1,24 @@ +using System; +using Aspose.Cells; + +namespace AsposeCellsVbaSignatureValidation +{ + class Program + { + static void Main() + { + // Load a workbook that contains a VBA project (macro-enabled file) + string workbookPath = "SignedWorkbook.xlsm"; + Workbook workbook = new Workbook(workbookPath); + + // Determine whether the VBA project is signed + bool isSigned = workbook.VbaProject.IsSigned; + Console.WriteLine("VBA Project Signed: " + isSigned); + + // Validate the digital signature of the VBA project + // The IsValidSigned property reflects the result of the validation + bool isSignatureValid = workbook.VbaProject.IsValidSigned; + Console.WriteLine("VBA Project Signature Valid: " + isSignatureValid); + } + } +} \ No newline at end of file diff --git a/macro-project/validate-the-vba-projects-signature-against-a-trusted-root-authority-and-output-validation-status.cs b/macro-project/validate-the-vba-projects-signature-against-a-trusted-root-authority-and-output-validation-status.cs new file mode 100644 index 0000000000..236c1d139a --- /dev/null +++ b/macro-project/validate-the-vba-projects-signature-against-a-trusted-root-authority-and-output-validation-status.cs @@ -0,0 +1,29 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +class ValidateVbaSignature +{ + static void Main() + { + // Load a workbook that contains a VBA project. + Workbook workbook = new Workbook("SignedWorkbook.xlsm"); + + // Access the VBA project. + VbaProject vbaProject = workbook.VbaProject; + + // Determine whether the VBA project is signed. + if (vbaProject.IsSigned) + { + Console.WriteLine("VBA project is signed."); + + // Validate the signature against the trusted root authority. + // The IsValidSigned property returns true if the signature is valid. + Console.WriteLine("Signature valid: " + vbaProject.IsValidSigned); + } + else + { + Console.WriteLine("VBA project is not signed."); + } + } +} \ No newline at end of file diff --git a/macro-project/verify-that-vba-project-signature-becomes-invalid-after-modifying-macro-code-without-resigning.cs b/macro-project/verify-that-vba-project-signature-becomes-invalid-after-modifying-macro-code-without-resigning.cs new file mode 100644 index 0000000000..637fc9c282 --- /dev/null +++ b/macro-project/verify-that-vba-project-signature-becomes-invalid-after-modifying-macro-code-without-resigning.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsExamples +{ + public class VbaSignatureInvalidAfterModificationDemo + { + public static void Main() + { + try + { + Run(); + } + catch (Exception ex) + { + Console.WriteLine("Unhandled error: " + ex.Message); + } + } + + public static void Run() + { + // Path to the signed workbook (replace with actual path) + string signedWorkbookPath = "signed.xlsm"; + + // Prevent FileNotFoundException + if (!File.Exists(signedWorkbookPath)) + { + Console.WriteLine($"File not found: {signedWorkbookPath}"); + return; + } + + try + { + // Load the workbook that already contains a signed VBA project + Workbook workbook = new Workbook(signedWorkbookPath); + + // Show initial signature status + Console.WriteLine("Initial state:"); + Console.WriteLine("Is VBA Project Signed: " + workbook.VbaProject.IsSigned); + Console.WriteLine("Is Signature Valid: " + workbook.VbaProject.IsValidSigned); + + // Ensure at least one module exists; add one if necessary + if (workbook.VbaProject.Modules.Count == 0) + { + // Use cast to VbaModuleType to avoid enum version issues + int newModuleIdx = workbook.VbaProject.Modules.Add((VbaModuleType)0, "Mod1"); + workbook.VbaProject.Modules[newModuleIdx].Codes = "Sub Dummy()\nEnd Sub"; + } + + // Append a comment line to the first module's code + VbaModule firstModule = workbook.VbaProject.Modules[0]; + firstModule.Codes += "\n' Modification made without re‑signing"; + + // Save the modified workbook to a memory stream (preserving macro format) + using (MemoryStream ms = new MemoryStream()) + { + workbook.Save(ms, SaveFormat.Xlsm); + ms.Position = 0; // reset stream position for reading + + // Reload the workbook from the stream + Workbook modifiedWorkbook = new Workbook(ms); + + // Show signature status after modification + Console.WriteLine("\nAfter modification (without re‑signing):"); + Console.WriteLine("Is VBA Project Signed: " + modifiedWorkbook.VbaProject.IsSigned); + Console.WriteLine("Is Signature Valid: " + modifiedWorkbook.VbaProject.IsValidSigned); + } + } + catch (Exception ex) + { + Console.WriteLine("Runtime error: " + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/macro-project/verify-the-vba-projects-digital-signature-status-using-the-issigned-property.cs b/macro-project/verify-the-vba-projects-digital-signature-status-using-the-issigned-property.cs new file mode 100644 index 0000000000..8488abb4b5 --- /dev/null +++ b/macro-project/verify-the-vba-projects-digital-signature-status-using-the-issigned-property.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AspNetExamples +{ + public class VbaSignatureVerifier + { + public static void Main(string[] args) + { + Run(); + } + + public static void Run() + { + // Path to the macro-enabled workbook (adjust as needed) + string workbookPath = "sample.xlsm"; + + // Verify that the file exists before attempting to load + if (!File.Exists(workbookPath)) + { + Console.WriteLine($"Error: File not found - {workbookPath}"); + return; + } + + try + { + // Load the workbook + Workbook workbook = new Workbook(workbookPath); + + // Get the VBA project from the workbook + var vbaProject = workbook.VbaProject; + + // Verify if the VBA project is signed and output the result + if (vbaProject != null && vbaProject.IsSigned) + { + Console.WriteLine("VBA project is signed."); + Console.WriteLine("Signature is valid: " + vbaProject.IsValidSigned); + } + else + { + Console.WriteLine("VBA project is not signed."); + } + } + catch (Exception ex) + { + // Handle any runtime exceptions gracefully + Console.WriteLine("An error occurred while processing the workbook:"); + Console.WriteLine(ex.Message); + } + } + } +} \ No newline at end of file diff --git a/macro-project/verify-whether-the-vba-project-in-the-loaded-workbook-is-password-protected.cs b/macro-project/verify-whether-the-vba-project-in-the-loaded-workbook-is-password-protected.cs new file mode 100644 index 0000000000..8ce21128dc --- /dev/null +++ b/macro-project/verify-whether-the-vba-project-in-the-loaded-workbook-is-password-protected.cs @@ -0,0 +1,24 @@ +using System; +using Aspose.Cells; +using Aspose.Cells.Vba; + +namespace AsposeCellsVbaCheck +{ + class Program + { + static void Main() + { + // Load the workbook that may contain a VBA project + Workbook workbook = new Workbook("input.xlsm"); + + // Get the VBA project from the workbook + VbaProject vbaProject = workbook.VbaProject; + + // Determine if the VBA project is protected with a password + bool isPasswordProtected = vbaProject.IsProtected; + + // Output the verification result + Console.WriteLine("VBA Project password protected: " + isPasswordProtected); + } + } +} \ No newline at end of file diff --git a/macro-project/wrap-signing-operation-in-trycatch-block-to-handle-exceptions-and-log-error-details.cs b/macro-project/wrap-signing-operation-in-trycatch-block-to-handle-exceptions-and-log-error-details.cs new file mode 100644 index 0000000000..e8c5a3493d --- /dev/null +++ b/macro-project/wrap-signing-operation-in-trycatch-block-to-handle-exceptions-and-log-error-details.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using Aspose.Cells; +using Aspose.Cells.DigitalSignatures; + +namespace AsposeCellsExamples +{ + public class DigitalSignatureWithExceptionHandlingDemo + { + public static void Run() + { + try + { + // Create a new workbook and add sample content + Workbook workbook = new Workbook(); + workbook.Worksheets[0].Cells["A1"].PutValue("Document requiring digital signature"); + + // Certificate file path and password + string certPath = "mycertificate.pfx"; + string certPassword = "123456"; + + // Ensure the certificate file exists + if (!File.Exists(certPath)) + { + Console.WriteLine($"Certificate file not found: {certPath}"); + return; + } + + // Load the certificate + X509Certificate2 certificate = new X509Certificate2(); + certificate.Import(certPath, certPassword, X509KeyStorageFlags.DefaultKeySet); + + // Create a digital signature instance + DigitalSignature signature = new DigitalSignature( + certificate, + "Approved by QA", + DateTime.UtcNow); + + // Add the signature to a collection + DigitalSignatureCollection signatures = new DigitalSignatureCollection(); + signatures.Add(signature); + + // Apply the digital signature to the workbook + workbook.SetDigitalSignature(signatures); + + // Save the signed workbook + string outputPath = "SignedWorkbook.xlsx"; + workbook.Save(outputPath); + + Console.WriteLine("Workbook signed and saved successfully."); + } + catch (Exception ex) + { + // Log detailed error information + Console.WriteLine("An error occurred during the signing process:"); + Console.WriteLine($"Message: {ex.Message}"); + Console.WriteLine($"StackTrace: {ex.StackTrace}"); + if (ex.InnerException != null) + { + Console.WriteLine($"Inner Exception: {ex.InnerException.Message}"); + } + } + } + } + + // Entry point for the application + public class Program + { + public static void Main(string[] args) + { + DigitalSignatureWithExceptionHandlingDemo.Run(); + } + } +} \ No newline at end of file diff --git a/macro-project/write-validation-errors-to-a-text-file-for-later-analysis-and-compliance-reporting.cs b/macro-project/write-validation-errors-to-a-text-file-for-later-analysis-and-compliance-reporting.cs new file mode 100644 index 0000000000..efe8c22d8b --- /dev/null +++ b/macro-project/write-validation-errors-to-a-text-file-for-later-analysis-and-compliance-reporting.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using Aspose.Cells; + +namespace AsposeCellsValidationErrorReport +{ + class Program + { + static void Main() + { + // Create a new workbook and get the first worksheet + Workbook workbook = new Workbook(); + Worksheet sheet = workbook.Worksheets[0]; + + // Define a validation for cells A1:A5 (whole numbers between 10 and 20) + CellArea area = CellArea.CreateCellArea("A1", "A5"); + int validationIndex = sheet.Validations.Add(area); + Validation validation = sheet.Validations[validationIndex]; + validation.Type = ValidationType.WholeNumber; + validation.Operator = OperatorType.Between; + validation.Formula1 = "10"; + validation.Formula2 = "20"; + validation.AlertStyle = ValidationAlertType.Stop; + validation.ErrorTitle = "Invalid Input"; + validation.ErrorMessage = "Value must be between 10 and 20."; + validation.ShowError = true; + + // Insert some test values (some valid, some invalid) + sheet.Cells["A1"].PutValue(5); // Invalid + sheet.Cells["A2"].PutValue(15); // Valid + sheet.Cells["A3"].PutValue(25); // Invalid + sheet.Cells["A4"].PutValue(12); // Valid + sheet.Cells["A5"].PutValue(8); // Invalid + + // Prepare a text file to store validation error details + string errorReportPath = "ValidationErrors.txt"; + using (StreamWriter writer = new StreamWriter(errorReportPath, false)) + { + // Iterate through all validations in the worksheet + foreach (Validation val in sheet.Validations) + { + // For each area covered by the validation, check each cell + foreach (CellArea valArea in val.Areas) + { + for (int row = valArea.StartRow; row <= valArea.EndRow; row++) + { + for (int col = valArea.StartColumn; col <= valArea.EndColumn; col++) + { + Cell cell = sheet.Cells[row, col]; + // If the cell value violates the validation, write details to the file + if (!IsCellValueValid(cell, val)) + { + string cellName = CellsHelper.CellIndexToName(row, col); + writer.WriteLine($"Cell {cellName}: {val.ErrorMessage}"); + } + } + } + } + } + } + + // Save the workbook (optional, just to keep the file) + workbook.Save("ValidationDemo.xlsx"); + } + + // Helper method to evaluate whether a cell satisfies a given validation + private static bool IsCellValueValid(Cell cell, Validation validation) + { + // Use the built‑in validation check by attempting to apply the rule. + // Aspose.Cells does not expose a direct method, so we perform a simple check + // for WholeNumber between two values as an example. + if (validation.Type == ValidationType.WholeNumber && validation.Operator == OperatorType.Between) + { + if (double.TryParse(cell.StringValue, out double numericValue)) + { + if (double.TryParse(validation.Formula1, out double lower) && + double.TryParse(validation.Formula2, out double upper)) + { + return numericValue >= lower && numericValue <= upper; + } + } + // Non‑numeric or out of range values are invalid + return false; + } + + // For other validation types, assume valid (extend as needed) + return true; + } + } +} \ No newline at end of file