davca-toolkit/learning/solidworks/readasm/Program.cs @ 6c5a164a
| 6c5a164a | wcadmin | using System;
|
|
using System.Collections.Generic;
|
|||
using System.IO;
|
|||
using System.Text;
|
|||
using SolidWorks.Interop.sldworks;
|
|||
using SolidWorks.Interop.swconst;
|
|||
namespace ReadAsmApp
|
|||
{
|
|||
class Program
|
|||
{
|
|||
static void Main(string[] args)
|
|||
{
|
|||
SldWorks? swApp = null;
|
|||
try
|
|||
{
|
|||
Console.WriteLine("Connecting to SolidWorks...");
|
|||
swApp = Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")!) as SldWorks;
|
|||
if (swApp == null)
|
|||
{
|
|||
Console.WriteLine("Could not connect to SolidWorks.");
|
|||
return;
|
|||
}
|
|||
string asmPath = Path.Combine(Directory.GetCurrentDirectory(), "assets", "BENCH_VICE_ASSEMBLY", "Assembly.SLDASM");
|
|||
if (!File.Exists(asmPath))
|
|||
{
|
|||
Console.WriteLine($"File not found: {asmPath}");
|
|||
return;
|
|||
}
|
|||
int pref = (int)swUserPreferenceToggle_e.swExtRefUpdateCompNames;
|
|||
bool oldPrefValue = swApp.GetUserPreferenceToggle(pref);
|
|||
swApp.SetUserPreferenceToggle(pref, false);
|
|||
int errors = 0;
|
|||
int warnings = 0;
|
|||
ModelDoc2 swModel = swApp.OpenDoc6(asmPath, (int)swDocumentTypes_e.swDocASSEMBLY, (int)swOpenDocOptions_e.swOpenDocOptions_Silent, "", ref errors, ref warnings);
|
|||
if (swModel == null)
|
|||
{
|
|||
Console.WriteLine($"Failed to open document. Errors: {errors}");
|
|||
return;
|
|||
}
|
|||
Console.WriteLine("\n--- Running Tests: Read & Update Component Name ---");
|
|||
// 1. Initial Read
|
|||
var initialData = ReadAssembly(swModel);
|
|||
string targetToRename = "";
|
|||
string newBaseName = "";
|
|||
if (initialData.Exists(c => c.Name == "BAR GLOBES-1"))
|
|||
{
|
|||
targetToRename = "BAR GLOBES-1";
|
|||
newBaseName = "BAR GLOBES-RENAMED";
|
|||
}
|
|||
else if (initialData.Exists(c => c.Name.StartsWith("BAR GLOBES-RENAMED")))
|
|||
{
|
|||
targetToRename = initialData.Find(c => c.Name.StartsWith("BAR GLOBES-RENAMED"))!.Name;
|
|||
newBaseName = "BAR GLOBES";
|
|||
}
|
|||
else if (initialData.Exists(c => c.Name.StartsWith("BAR GLOBES")))
|
|||
{
|
|||
targetToRename = initialData.Find(c => c.Name.StartsWith("BAR GLOBES"))!.Name;
|
|||
newBaseName = "BAR GLOBES-RENAMED";
|
|||
}
|
|||
if (!string.IsNullOrEmpty(targetToRename))
|
|||
{
|
|||
Console.WriteLine($"\n[Test] Updating name from '{targetToRename}' to base name '{newBaseName}'...");
|
|||
bool updateSuccess = UpdateComponentName(swModel, targetToRename, newBaseName);
|
|||
Console.WriteLine($"[Test] Update operation executed? {updateSuccess}");
|
|||
Console.WriteLine("\n[Test] Saving assembly to disk...");
|
|||
int saveErrors = 0;
|
|||
int saveWarnings = 0;
|
|||
bool saved = swModel.Save3((int)swSaveAsOptions_e.swSaveAsOptions_Silent, ref saveErrors, ref saveWarnings);
|
|||
Console.WriteLine($"[Test] Assembly saved? {saved} (Errors: {saveErrors}, Warnings: {saveWarnings})");
|
|||
}
|
|||
else
|
|||
{
|
|||
Console.WriteLine("\n[Test] Target component for renaming not found. Skipping rename step.");
|
|||
}
|
|||
// 5. Final Read and CSV Export
|
|||
Console.WriteLine("\n--- Generating Final CSV ---");
|
|||
var finalData = ReadAssembly(swModel);
|
|||
string csvPath = Path.Combine(Directory.GetCurrentDirectory(), "assembly_data.csv");
|
|||
WriteToCsv(csvPath, initialData, finalData);
|
|||
Console.WriteLine($"\nSuccessfully exported data to: {csvPath}");
|
|||
// Clean up
|
|||
swApp.CloseDoc(asmPath);
|
|||
swApp.SetUserPreferenceToggle(pref, oldPrefValue);
|
|||
}
|
|||
catch (Exception ex)
|
|||
{
|
|||
Console.WriteLine($"An error occurred: {ex.Message}");
|
|||
}
|
|||
finally
|
|||
{
|
|||
if (swApp != null)
|
|||
{
|
|||
swApp.ExitApp();
|
|||
swApp = null;
|
|||
}
|
|||
GC.Collect();
|
|||
GC.WaitForPendingFinalizers();
|
|||
}
|
|||
}
|
|||
public static List<ComponentData> ReadAssembly(ModelDoc2 swModel)
|
|||
{
|
|||
List<ComponentData> componentList = new List<ComponentData>();
|
|||
Configuration swConfig = (Configuration)swModel.GetActiveConfiguration();
|
|||
Component2 rootComp = (Component2)swConfig.GetRootComponent3(true);
|
|||
TraverseComponent(rootComp, 0, componentList);
|
|||
return componentList;
|
|||
}
|
|||
public static bool UpdateComponentName(ModelDoc2 swModel, string oldFullName, string newBaseName)
|
|||
{
|
|||
AssemblyDoc swAsm = (AssemblyDoc)swModel;
|
|||
Component2 comp = (Component2)swAsm.GetComponentByName(oldFullName);
|
|||
if (comp == null)
|
|||
{
|
|||
Console.WriteLine($"Component '{oldFullName}' not found in the assembly.");
|
|||
return false;
|
|||
}
|
|||
// CRITICAL: Component must be selected before setting Name2
|
|||
comp.Select4(false, null, false);
|
|||
// Update the name
|
|||
comp.Name2 = newBaseName;
|
|||
// Rebuild to apply changes
|
|||
swModel.ForceRebuild3(false);
|
|||
// We do not save to disk here; keeping it in-memory for the session is sufficient for the test
|
|||
// but we can try to save if needed. Since the user test operates on the in-memory object, this works.
|
|||
return true;
|
|||
}
|
|||
static void TraverseComponent(Component2 swComp, int level, List<ComponentData> list)
|
|||
{
|
|||
if (swComp == null) return;
|
|||
object[] children = (object[])swComp.GetChildren();
|
|||
if (children != null)
|
|||
{
|
|||
foreach (Component2 child in children)
|
|||
{
|
|||
ComponentData data = new ComponentData
|
|||
{
|
|||
Level = level + 1,
|
|||
Name = child.Name2,
|
|||
Path = child.GetPathName(),
|
|||
Configuration = child.ReferencedConfiguration,
|
|||
IsSuppressed = child.IsSuppressed()
|
|||
};
|
|||
if (!data.IsSuppressed)
|
|||
{
|
|||
ModelDoc2 model = (ModelDoc2)child.GetModelDoc2();
|
|||
if (model != null)
|
|||
{
|
|||
MassProperty swMassProp = (MassProperty)model.Extension.CreateMassProperty();
|
|||
if (swMassProp != null)
|
|||
{
|
|||
data.Mass = swMassProp.Mass;
|
|||
data.Volume = swMassProp.Volume;
|
|||
}
|
|||
}
|
|||
}
|
|||
list.Add(data);
|
|||
TraverseComponent(child, level + 1, list);
|
|||
}
|
|||
}
|
|||
}
|
|||
static void WriteToCsv(string filePath, List<ComponentData> originalData, List<ComponentData> finalData)
|
|||
{
|
|||
StringBuilder sb = new StringBuilder();
|
|||
sb.AppendLine("Level,Old Component Name,New Component Name,Configuration,Mass (kg),Volume (m^3),Path,Suppressed");
|
|||
for (int i = 0; i < finalData.Count; i++)
|
|||
{
|
|||
var newItem = finalData[i];
|
|||
var oldItem = i < originalData.Count ? originalData[i] : newItem;
|
|||
sb.AppendLine($"{newItem.Level},\"{oldItem.Name}\",\"{newItem.Name}\",\"{newItem.Configuration}\",{newItem.Mass:F5},{newItem.Volume:F5},\"{newItem.Path}\",{newItem.IsSuppressed}");
|
|||
}
|
|||
File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8);
|
|||
}
|
|||
}
|
|||
public class ComponentData
|
|||
{
|
|||
public int Level { get; set; }
|
|||
public string Name { get; set; } = string.Empty;
|
|||
public string Path { get; set; } = string.Empty;
|
|||
public string Configuration { get; set; } = string.Empty;
|
|||
public double Mass { get; set; }
|
|||
public double Volume { get; set; }
|
|||
public bool IsSuppressed { get; set; }
|
|||
}
|
|||
}
|