# VBA 与 C# 宏

复杂 API 调用可以放在 SOLIDWORKS 宏中执行，但普通建模、文档管理和反馈读取优先直接使用 COM。宏引擎的成功状态不等于业务成功，必须验证实际输出。

## 1. 运行已有宏

```aardio
import com.sldWorks;
var sw,err = com.sldWorks(false);
if(!sw){ print(err); return; }

var ok,macroError = sw.RunMacro("/macros/example.swp","","Main");
print(ok,macroError);
```

`RunMacro(path,module,procedure,options)` 包装 `RunMacro2`：默认模块为空字符串、入口 `Main`、选项 0。文本宏可通过 `VBA` 方法运行；支持的 DLL 宏可由 `NetCompiler` 生成。

运行不可信宏相当于执行程序。不要用宏自动点击安全警告、关闭错误提示或跳过验证。VBA `MsgBox`、`SendMsgToUser` 等会阻塞自动化，示例改用文件反馈。

## 2. 文本 SWB 宏与真实反馈

```aardio
import com.sldWorks;
var sw,err = com.sldWorks(false);
if(!sw){ print(err); return; }
var outputPath = io.tmpname("sw-vba-",".txt");

var code = /***
Sub main()
    Dim app As Object
    Dim fso As Object
    Dim stream As Object
    Set app = Application.SldWorks
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set stream = fso.CreateTextFile("<?= owner.path ?>", True)
    stream.Write app.RevisionNumber
    stream.Close
End Sub
***/;

var ok,macroError = sw.VBA(code,{path=outputPath});
if(!ok){ print(macroError); return; }
var text,readError = string.load(outputPath);
if(!text){ print("宏未生成预期结果",readError); return; }
print("宏回读版本：",text);
io.remove(outputPath);
```

`VBA(code,templateOwner)` 自动生成临时 `.swb`，运行后删除。模板失败会在运行宏之前返回 `null,说明`；宏引擎失败返回 `false,原生错误码`；COM 调用异常也会清理临时文件并返回 `null,说明`。

文本 SWB 按系统 ANSI 代码页传入。不要依赖它传输代码页无法表示的任意 Unicode 字符；对这类数据优先用 UTF-8 文件、JSON 和 C#。模板中的路径应来自受信任的本地参数。

## 3. 模板传入表与数组

`<? ... ?>` 内是 aardio 代码，`<?= expression ?>` 输出表达式。表和数组会被转为 JSON，再生成宏侧的 `JsonParse` 表达式。

```aardio
import com.sldWorks;
var sw,err = com.sldWorks(false);
if(!sw){ print(err); return; }
var code = /***
Sub main()
    Dim values As Object
    Set values = <?= owner.values ?>
    Dim app As Object
    Set app = Application.SldWorks
    If Not app.ActiveDoc Is Nothing Then
        app.ActiveDoc.SummaryInfo(0) = values("title")
    End If
End Sub
***/;

// 本段会修改活动文档摘要，请先核对活动文档。
var ok,macroError = sw.VBA(code,{values={title="Created by aardio"}});
print(ok,macroError);
```

- aardio 表的名值对对应宏侧字典，数组对应集合。
- 普通字符串输出不会自动为目标语言补上字符串引号；结构化数据更适合通过表/数组传递。
- 只生成代码而不执行可用 `com.sldWorks.loadcode("VBA",code,templateOwner)`。
- 模板语法错误或运行时错误会返回，不会继续运行残缺宏；模板结束后恢复原来的 `print`。

## 4. 编译并运行 C# 宏

```aardio
import com.sldWorks;
import dotNet;
var sw,err = com.sldWorks(false);
if(!sw){ print(err); return; }

var outputPath = io.tmpname("sw-csharp-",".txt");
var macroPath = io.tmpname("sw-macro-",".dll");
var compiler = sw.NetCompiler("C#");
compiler.ownerArgs.outputPath = outputPath;
compiler.Source = /***
namespace ExampleMacro
{
    public class SolidWorksMacro
    {
        <?= owner.start("SolidWorksMacro") ?>
        public void Main()
        {
            File.WriteAllText(@"<?= owner.outputPath ?>", swApp.RevisionNumber());
        }
    }
}
***/;

var assembly,compileError = compiler.Compile(macroPath);
if(!assembly){ print(compileError); return; }
var ok,macroError = sw.RunMacro(macroPath);
if(!ok){ print(macroError); return; }
var text,readError = string.load(outputPath);
if(!text){ print("宏未产生预期反馈",readError); return; }
print("C# 宏回读版本：",text);
io.remove(outputPath);
// DLL 可能仍被 SOLIDWORKS 的 CLR 加载；关闭会话后再清理 macroPath。
```

`NetCompiler` 引用当前连接实例安装目录中的 API 程序集，默认添加常用 `using`。`owner.start("类名")` 生成 `swApp` 字段及宏初始化入口；类名必须一致。

初始化代码会在安装根目录和 `api\redist` 查找依赖程序集，找不到时交给后续解析器，不无条件抛出文件找不到异常。不要把当前计算机安装目录写死到通用业务逻辑中。

aardio 使用的 CLR 编译器受本机 .NET 版本约束，不能直接假设支持最新 C# 语法。示例使用保守语法。

## 5. 宏结果协议建议

原有 `RunMacro` / `VBA` 不返回任意业务对象。可以选择：

- 宏修改模型，aardio 再读取尺寸、体积、特征与保存状态。
- 宏写唯一结果文件，aardio 验证文件本次创建、内容完整且对应当前任务。
- 复杂 C# 宏写 UTF-8 JSON，包含明确的业务成功标志、错误描述、目标路径和结果值。

每次使用唯一文件名，避免误读上次成功遗留的结果。单次宏不要囊括太多无法观测的步骤。程序忙或调用中断后先检查当前状态，再决定是否重试；不要重复执行不可幂等的建模动作。

[返回首页](index.html)
