using System.Runtime.InteropServices;
using Sbroenne.ExcelMcp.ComInterop;
using Sbroenne.ExcelMcp.ComInterop.Session;
namespace Sbroenne.ExcelMcp.Core.Commands;
/// <summary>
/// VBA script operations (Run)
/// </summary>
public partial class VbaCommands
{
/// <inheritdoc />
public void Run(IExcelBatch batch, string procedureName, TimeSpan? timeout, params string[] parameters)
{
var (isValid, validationError) = ValidateVbaFile(batch.WorkbookPath);
if (!isValid)
{
throw new ArgumentException(validationError, nameof(batch));
}
// Check VBA trust BEFORE attempting operation
if (!IsVbaTrustEnabled())
{
throw new InvalidOperationException(VbaTrustErrorMessage);
}
batch.Execute((ctx, ct) =>
{
try
{
if (parameters.Length == 0)
{
ctx.App.Run(procedureName);
}
else
{
object[] paramObjects = parameters.Cast<object>().ToArray();
ctx.App.Run(procedureName, paramObjects);
}
return 0;
}
catch (COMException comEx) when (comEx.Message.Contains("programmatic access", StringComparison.OrdinalIgnoreCase) ||
comEx.ErrorCode == unchecked((int)0x800A03EC))
{
throw new InvalidOperationException(VbaTrustErrorMessage, comEx);
}
});
}
/// <inheritdoc />
public void Delete(IExcelBatch batch, string moduleName)
{
var (isValid, validationError) = ValidateVbaFile(batch.WorkbookPath);
if (!isValid)
{
throw new InvalidOperationException(validationError);
}
// Check VBA trust BEFORE attempting operation
if (!IsVbaTrustEnabled())
{
throw new InvalidOperationException(VbaTrustErrorMessage);
}
batch.Execute((ctx, ct) =>
{
dynamic? vbaProject = null;
dynamic? vbComponents = null;
dynamic? targetComponent = null;
try
{
vbaProject = ctx.Book.VBProject;
vbComponents = vbaProject.VBComponents;
for (int i = 1; i <= vbComponents.Count; i++)
{
dynamic? component = null;
try
{
component = vbComponents.Item(i);
if (component.Name == moduleName)
{
targetComponent = component;
component = null; // Don't release - we're keeping it
break;
}
}
finally
{
if (component != null)
{
ComUtilities.Release(ref component);
}
}
}
if (targetComponent == null)
{
throw new InvalidOperationException($"Module '{moduleName}' not found.");
}
vbComponents.Remove(targetComponent);
return 0;
}
catch (COMException comEx) when (comEx.Message.Contains("programmatic access", StringComparison.OrdinalIgnoreCase) ||
comEx.ErrorCode == unchecked((int)0x800A03EC))
{
throw new InvalidOperationException(VbaTrustErrorMessage, comEx);
}
finally
{
ComUtilities.Release(ref targetComponent);
ComUtilities.Release(ref vbComponents);
ComUtilities.Release(ref vbaProject);
}
});
}
}