适用版本:SOLIDWORKS 2018 及以上(VBA 宏)风险提示:本文涉及的操作会修改模型显示属性,建议操作前备份文件。
在 SOLIDWORKS 日常建模与装配过程中,模型颜色混乱是一个高频痛点。颜色来源往往分散在多个层级,难以追溯:
最终结果是:同一个零件在不同装配层级、不同显示状态下呈现不同颜色,严重影响模型评审和出图效率。
SOLIDWORKS 的外观系统采用分层覆盖机制,优先级从高到低依次为:面(Face)→ 特征(Feature)→ 实体(Body)→ 零件(Part)→ 组件(Component)→ 材质(Material)
关键认知:
许多初学者会尝试用 SelectByID2 + EditDelete 来删除外观,但这种方式存在明显风险:
正确思路:通过官方 API 直接操作外观对象,避免任何选择-删除操作。
这是零件文档的方法,官方描述为:
Removes all display states and appearances from this part document.
行为:删除零件中所有 Display State,并创建一个无外观的默认 Display State。这会同时清除面、特征、实体、零件级别的外观。
⚠️ 注意:
以下代码针对原文进行了以下修正:
Option Explicit
'========================
' 常量定义(确保低版本兼容)
'========================
Const swDocPART AsLong=1
Const swDocASSEMBLY AsLong=2
'========================
' 主入口
'========================
Sub ClearAllAppearances()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
If swModel IsNothingThen
MsgBox "请先打开一个零件或装配体文件。", vbExclamation
ExitSub
EndIf
Dim docType AsLong
docType = swModel.GetType
SelectCase docType
Case swDocPART
' 清理当前零件的所有外观
ClearPartAllAppearances swModel
Case swDocASSEMBLY
' 清理装配体:包括组件覆盖 + 递归清理子零件/子装配
ClearAssemblyAllAppearances swModel
CaseElse
MsgBox "仅支持零件(.sldprt)和装配体(.sldasm)文件。", vbExclamation
ExitSub
EndSelect
swModel.EditRebuild3
swModel.GraphicsRedraw2
MsgBox "外观清理完成。建议保存文件以保留更改。", vbInformation
EndSub
'========================
' 零件级:清除所有外观(面/特征/实体/零件/Display State)
'========================
Sub ClearPartAllAppearances(ByVal swModel As SldWorks.ModelDoc2)
If swModel IsNothingThenExitSub
Dim swPart As SldWorks.PartDoc
Set swPart = swModel
OnErrorResumeNext
' 方法1:RemoveAllDisplayStates — 清除零件内所有层级的外观
' 注意:这会删除所有自定义 Display State!
swPart.RemoveAllDisplayStates
OnErrorGoTo0
' 方法2(备选):如果 RemoveAllDisplayStates 不满足需求,
' 可以遍历 Body 并调用 RemoveMaterialProperty 做更细粒度控制
' 以下代码演示如何单独清除 Body 级别外观:
'
' Dim vBodies As Variant
' Dim swBody As SldWorks.Body2
' Dim vConfigNames As Variant
' vConfigNames = swModel.GetConfigurationNames
'
' vBodies = swPart.GetBodies2(swSolidBody, True)
' If Not IsEmpty(vBodies) Then
' Dim i As Long
' For i = 0 To UBound(vBodies)
' Set swBody = vBodies(i)
' swBody.RemoveMaterialProperty swAllConfiguration, vConfigNames
' Next i
' End If
EndSub
'========================
' 装配体级:递归清理
'========================
Sub ClearAssemblyAllAppearances(ByVal swModel As SldWorks.ModelDoc2)
If swModel IsNothingThenExitSub
Dim swAssy As SldWorks.AssemblyDoc
Set swAssy = swModel
' 获取顶层组件(包含所有层级)
Dim vComps AsVariant
vComps = swAssy.GetComponents(True)
If IsEmpty(vComps)ThenExitSub
Dim i AsLong
Dim swComp As SldWorks.Component2
Dim swCompModel As SldWorks.ModelDoc2
For i =0To UBound(vComps)
Set swComp = vComps(i)
If swComp IsNothingThenGoTo NextComponent
' 跳过被压缩的组件
If swComp.GetSuppression2 = swComponentSuppressed ThenGoTo NextComponent
' 跳过轻化模式组件(轻化模式下无法获取完整模型数据)
If swComp.GetSuppression2 = swComponentLightweight Then
Debug.Print "跳过轻化组件: "& swComp.Name2
GoTo NextComponent
EndIf
Set swCompModel = swComp.GetModelDoc2
If swCompModel IsNothingThenGoTo NextComponent
' 根据组件类型分别处理
SelectCase swCompModel.GetType
Case swDocPART
' 对零件文件本身清理外观
ClearPartAllAppearances swCompModel
Case swDocASSEMBLY
' 对子装配递归处理
ClearAssemblyAllAppearances swCompModel
EndSelect
' ⚠️ 重要说明:
' 上述操作清理的是零件/子装配文件内部的外观。
' 如果装配体中对组件有 Component Appearance 覆盖,
' 需要额外通过 AssemblyDoc 或 Component2 的 API 清除。
' 目前 SOLIDWORKS API 中直接移除 Component Appearance 的方法有限,
' 常见做法是通过 DisplayManager 或 Selection + RemoveAppearance 处理。
NextComponent:
Next i
EndSub
复制成功
外观层级
是否可清除
说明
Face
✅
通过 RemoveAllDisplayStates 清除
Feature
✅
通过 RemoveAllDisplayStates 清除
Body
✅
通过 RemoveAllDisplayStates 清除(或单独遍历 Body)
Part
✅
通过 RemoveAllDisplayStates 清除
Component(装配体覆盖)
⚠️ 部分
RemoveAllDisplayStates 在装配体中仅清除组件级外观,但本文递归逻辑主要操作的是零件文件本身
Material
❌
材质颜色不会被移除,模型会恢复为材质默认色
装配体结构是树状的:
顶层装配体
├── 子装配体 A │ ├── 零件 1 │ └── 零件 2 └── 子装配体 B └── 零件 3
如果不递归处理,只能清理当前装配层级,子装配体及其内部零件的颜色完全不会变化。
基于本文代码,可以进一步扩展为:
SOLIDWORKS 外观问题的本质是多层级覆盖导致的显示状态不一致。解决思路应当遵循:
本文提供的代码是一个基础且可靠的起始版本,适用于大多数"一键归零"场景。如需更精细的控制(如保留某些 Display State、仅清除特定层级),建议在此基础上结合 RenderMaterial、DisplayStateSetting 等 API 进行二次开发。
免责声明:本文代码仅供学习和参考,运行前请备份原始文件。作者不对因使用本文代码导致的文件损坏或数据丢失承担责任。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删