From 843f6ef1bee1bcef2328197c39c7b29f2a182dd8 Mon Sep 17 00:00:00 2001 From: aj Date: Thu, 19 Jan 2017 22:11:08 -0500 Subject: [PATCH] Add project files. --- ExportDXF.sln | 22 + ExportDXF/ExportDXF.csproj | 101 +++ ExportDXF/Forms/MainForm.Designer.cs | 149 +++++ ExportDXF/Forms/MainForm.cs | 688 +++++++++++++++++++++ ExportDXF/Forms/MainForm.resx | 120 ++++ ExportDXF/Program.cs | 21 + ExportDXF/Properties/AssemblyInfo.cs | 36 ++ ExportDXF/Properties/Resources.Designer.cs | 93 +++ ExportDXF/Properties/Resources.resx | 130 ++++ ExportDXF/Properties/Settings.Designer.cs | 30 + ExportDXF/Properties/Settings.settings | 7 + ExportDXF/Resources/edit_alt.png | Bin 0 -> 1330 bytes ExportDXF/Resources/play.png | Bin 0 -> 1134 bytes ExportDXF/Resources/stop_alt.png | Bin 0 -> 1602 bytes ExportDXF/Templates/Blank.drwdot | Bin 0 -> 21115 bytes 15 files changed, 1397 insertions(+) create mode 100644 ExportDXF.sln create mode 100644 ExportDXF/ExportDXF.csproj create mode 100644 ExportDXF/Forms/MainForm.Designer.cs create mode 100644 ExportDXF/Forms/MainForm.cs create mode 100644 ExportDXF/Forms/MainForm.resx create mode 100644 ExportDXF/Program.cs create mode 100644 ExportDXF/Properties/AssemblyInfo.cs create mode 100644 ExportDXF/Properties/Resources.Designer.cs create mode 100644 ExportDXF/Properties/Resources.resx create mode 100644 ExportDXF/Properties/Settings.Designer.cs create mode 100644 ExportDXF/Properties/Settings.settings create mode 100644 ExportDXF/Resources/edit_alt.png create mode 100644 ExportDXF/Resources/play.png create mode 100644 ExportDXF/Resources/stop_alt.png create mode 100644 ExportDXF/Templates/Blank.drwdot diff --git a/ExportDXF.sln b/ExportDXF.sln new file mode 100644 index 0000000..9a1043d --- /dev/null +++ b/ExportDXF.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportDXF", "ExportDXF\ExportDXF.csproj", "{05F21D73-FD31-4E77-8D9B-41C86D4D8305}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05F21D73-FD31-4E77-8D9B-41C86D4D8305}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05F21D73-FD31-4E77-8D9B-41C86D4D8305}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05F21D73-FD31-4E77-8D9B-41C86D4D8305}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05F21D73-FD31-4E77-8D9B-41C86D4D8305}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ExportDXF/ExportDXF.csproj b/ExportDXF/ExportDXF.csproj new file mode 100644 index 0000000..03b2606 --- /dev/null +++ b/ExportDXF/ExportDXF.csproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {05F21D73-FD31-4E77-8D9B-41C86D4D8305} + WinExe + Properties + ExportDXF + ExportDXF + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + False + C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\api\redist\SolidWorks.Interop.sldworks.dll + + + False + False + C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\api\redist\SolidWorks.Interop.swconst.dll + + + + + + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + PreserveNewest + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExportDXF/Forms/MainForm.Designer.cs b/ExportDXF/Forms/MainForm.Designer.cs new file mode 100644 index 0000000..664362c --- /dev/null +++ b/ExportDXF/Forms/MainForm.Designer.cs @@ -0,0 +1,149 @@ +namespace ExportDXF.Forms +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.BackColor = System.Drawing.Color.White; + this.textBox1.Location = new System.Drawing.Point(130, 17); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(348, 25); + this.textBox1.TabIndex = 2; + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.BackColor = System.Drawing.Color.White; + this.richTextBox1.Location = new System.Drawing.Point(12, 83); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(570, 181); + this.richTextBox1.TabIndex = 3; + this.richTextBox1.Text = ""; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(112, 17); + this.label1.TabIndex = 4; + this.label1.Text = "Active Document :"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(23, 51); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(101, 17); + this.label2.TabIndex = 4; + this.label2.Text = "Prefix files with :"; + // + // textBox2 + // + this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox2.Location = new System.Drawing.Point(130, 48); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(348, 25); + this.textBox2.TabIndex = 2; + // + // button2 + // + this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button2.Image = global::ExportDXF.Properties.Resources.edit_alt; + this.button2.Location = new System.Drawing.Point(536, 13); + this.button2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(46, 60); + this.button2.TabIndex = 0; + this.button2.UseVisualStyleBackColor = true; + this.button2.Visible = false; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button1.Image = global::ExportDXF.Properties.Resources.play; + this.button1.Location = new System.Drawing.Point(484, 13); + this.button1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(46, 60); + this.button1.TabIndex = 0; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(594, 276); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.richTextBox1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.MaximizeBox = false; + this.Name = "Form1"; + this.Text = "ExportDXF"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button2; + } +} + diff --git a/ExportDXF/Forms/MainForm.cs b/ExportDXF/Forms/MainForm.cs new file mode 100644 index 0000000..95970fe --- /dev/null +++ b/ExportDXF/Forms/MainForm.cs @@ -0,0 +1,688 @@ +using SolidWorks.Interop.sldworks; +using SolidWorks.Interop.swconst; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace ExportDXF.Forms +{ + public partial class MainForm : Form + { + private SldWorks sldWorks; + private BackgroundWorker worker; + private DrawingDoc templateDrawing; + private DateTime timeStarted; + + public MainForm() + { + InitializeComponent(); + + worker = new BackgroundWorker(); + worker.WorkerSupportsCancellation = true; + worker.DoWork += Worker_DoWork; + worker.RunWorkerCompleted += Worker_RunWorkerCompleted; + } + + private void Worker_DoWork(object sender, DoWorkEventArgs e) + { + timeStarted = DateTime.Now; + + Invoke(new MethodInvoker(() => + { + sldWorks.ActiveModelDocChangeNotify -= SldWorks_ActiveModelDocChangeNotify; + + button1.Image = Properties.Resources.stop_alt; + + if (richTextBox1.TextLength != 0) + richTextBox1.AppendText("\n\n"); + })); + + var model = sldWorks.ActiveDoc as ModelDoc2; + + Print("Started at " + DateTime.Now.ToShortTimeString()); + + CreateDXFTemplates(model); + } + + private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + Invoke(new MethodInvoker(() => + { + if (templateDrawing != null) + { + sldWorks.CloseDoc(((ModelDoc2)templateDrawing).GetTitle()); + templateDrawing = null; + } + + button1.Image = Properties.Resources.play; + })); + + var duration = DateTime.Now - timeStarted; + + Print("Run time: " + duration.ToReadableFormat()); + Print("Done.", Color.Green); + + sldWorks.ActiveModelDocChangeNotify += SldWorks_ActiveModelDocChangeNotify; + } + + private int SldWorks_ActiveModelDocChangeNotify() + { + if (InvokeRequired) + { + Invoke(new MethodInvoker(() => + { + SetCurrentDocName(); + })); + } + else + { + SetCurrentDocName(); + } + + return 1; + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + new Thread(new ThreadStart(() => + { + Invoke(new MethodInvoker(() => + { + Enabled = false; + sldWorks = Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")) as SldWorks; + + if (sldWorks == null) + { + MessageBox.Show("Failed to connect to SolidWorks."); + Application.Exit(); + return; + } + + sldWorks.Visible = true; + sldWorks.ActiveModelDocChangeNotify += SldWorks_ActiveModelDocChangeNotify; + SetCurrentDocName(); + Enabled = true; + })); + })) + .Start(); + } + + private void Print(string s) + { + Invoke(new MethodInvoker(() => + { + richTextBox1.AppendText(s + System.Environment.NewLine); + richTextBox1.ScrollToCaret(); + })); + } + + private void Print(string s, Color color) + { + Invoke(new MethodInvoker(() => + { + richTextBox1.AppendText(s + System.Environment.NewLine, color); + richTextBox1.ScrollToCaret(); + })); + } + + private void SetCurrentDocName() + { + var model = sldWorks.ActiveDoc as ModelDoc2; + + textBox1.Text = model != null ? model.GetTitle() : ""; + } + + private void button1_Click(object sender, EventArgs e) + { + if (worker.IsBusy) + { + worker.CancelAsync(); + return; + } + + worker.RunWorkerAsync(); + } + + private void CreateDXFTemplates(ModelDoc2 model) + { + if (model is PartDoc) + { + Print("Active document is a Part"); + ExportToDXF(model as PartDoc); + } + else if (model is DrawingDoc) + { + Print("Active document is a Drawing"); + ExportToDXF(model as DrawingDoc); + } + else if (model is AssemblyDoc) + { + Print("Active document is a Assembly"); + ExportToDXF(model as AssemblyDoc); + } + } + + private void ExportToDXF(DrawingDoc drawing) + { + Print("Finding BOM tables..."); + var bomTables = GetBomTables(drawing); + + if (bomTables.Count == 0) + { + Print("Error: Bill of materials not found.", Color.Red); + return; + } + + Print("Found " + bomTables.Count); + Print(""); + + foreach (var bom in bomTables) + { + if (worker.CancellationPending) + return; + + Print(bom.BomFeature.Name); + + Print("Fetching components..."); + + var items = GetItems(bom); + + Print("Found " + items.Count); + Print(""); + + ExportToDXF(items); + } + } + + private void ExportToDXF(PartDoc part) + { + var prefix = textBox2.Text; + var model = part as ModelDoc2; + var dir = GetSaveDir(); + + if (dir == null) + { + Print("Cancelled\n", Color.Red); + return; + } + + if (dir == null) + return; + + var name = model.ConfigurationManager.ActiveConfiguration.Name.ToLower() == "default" ? + model.GetTitle() : + string.Format("{0} [{1}]", model.GetTitle(), model.ConfigurationManager.ActiveConfiguration.Name); + + var savePath = Path.Combine(dir, prefix + name + ".dxf"); + + SavePartToDXF(part, savePath); + } + + private void ExportToDXF(AssemblyDoc assembly) + { + Print("Fetching components..."); + + var items = GetItems(assembly, false); + + Print("Found " + items.Count); + Print(""); + + ExportToDXF(items); + } + + private void ExportToDXF(IEnumerable items) + { + var savePath = GetSaveDir(); + var prefix = textBox2.Text; + + if (savePath == null) + { + Print("Cancelled\n", Color.Red); + return; + } + + templateDrawing = CreateDrawing(); + + Print(""); + + foreach (var item in items) + { + if (worker.CancellationPending) + break; + + var fileName = prefix + item.Name + ".dxf"; + var savepath = Path.Combine(savePath, fileName); + var part = item.Component.GetModelDoc2() as PartDoc; + + if (part == null) + continue; + + SavePartToDXF(part, item.Component.ReferencedConfiguration, savepath); + Application.DoEvents(); + } + } + + private static int? FindItemNumberColumn(TableAnnotation table) + { + try + { + if (table.RowCount == 0 || table.ColumnCount == 0) + return null; + + var consecutiveNumberCountPerColumn = new int[table.ColumnCount]; + + for (int columnIndex = 0; columnIndex < table.ColumnCount; ++columnIndex) + { + for (int rowIndex = 0; rowIndex < table.RowCount - 1; ++rowIndex) + { + var currentRowValue = table.Text[rowIndex, columnIndex]; + var nextRowValue = table.Text[rowIndex + 1, columnIndex]; + + int currentRowNum; + int nextRowNum; + + if (currentRowValue == null || !int.TryParse(currentRowValue, out currentRowNum)) + continue; // because currentRowValue is not a number + + if (nextRowValue == null || !int.TryParse(nextRowValue, out nextRowNum)) + continue; // because nextRowValue is not a number + + if (currentRowNum == (nextRowNum - 1)) + consecutiveNumberCountPerColumn[columnIndex]++; + } + } + + int index = 0; + int max = consecutiveNumberCountPerColumn[0]; + + for (int i = 1; i < consecutiveNumberCountPerColumn.Length; ++i) + { + if (consecutiveNumberCountPerColumn[i] > max) + { + index = i; + max = consecutiveNumberCountPerColumn[i]; + } + } + + return index; + } + catch + { + return null; + } + } + + private bool SavePartToDXF(PartDoc part, string savePath) + { + var partModel = part as ModelDoc2; + var config = partModel.ConfigurationManager.ActiveConfiguration.Name; + + return SavePartToDXF(part, config, savePath); + } + + private bool SavePartToDXF(PartDoc part, string partConfiguration, string savePath) + { + try + { + var partModel = part as ModelDoc2; + + if (partModel.IsSheetMetal() == false) + { + Print(partModel.GetTitle() + " - skipped, not sheet metal"); + return false; + } + + if (templateDrawing == null) + templateDrawing = CreateDrawing(); + + var sheet = templateDrawing.IGetCurrentSheet(); + var modelName = Path.GetFileNameWithoutExtension(partModel.GetPathName()); + sheet.SetName(modelName); + + + Print(partModel.GetTitle() + " - Creating flat pattern."); + SolidWorks.Interop.sldworks.View view; + view = templateDrawing.CreateFlatPatternViewFromModelView3(partModel.GetPathName(), partConfiguration, 0, 0, 0, false, false); + view.ShowSheetMetalBendNotes = true; + + var drawingModel = templateDrawing as ModelDoc2; + drawingModel.ViewZoomtofit2(); + + if (ShouldFlipView(view)) + { + Print(partModel.GetTitle() + " - Flipped view", Color.Blue); + view.FlipView = true; + } + + drawingModel.SaveAs(savePath); + + Print(partModel.GetTitle() + " - Saved to \"" + savePath + "\"", Color.Green); + Print(""); + + drawingModel.SelectByName(0, view.Name); + drawingModel.DeleteSelection(false); + + return true; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + return false; + } + } + + private string GetSaveDir() + { + string path = null; + + Invoke(new MethodInvoker(() => + { + var dlg = new FolderBrowserDialog(); + dlg.Description = "Where do you want to save the DXF files?"; + + path = dlg.ShowDialog() == DialogResult.OK ? dlg.SelectedPath : null; + })); + + return path; + } + + private bool ShouldFlipView(SolidWorks.Interop.sldworks.View view) + { + var notes = (view.GetNotes() as Array)?.Cast(); + + var upCount = 0; + var dnCount = 0; + + Note leftMost = null; + double leftMostValue = double.MaxValue; + + foreach (var note in notes) + { + var pt = (note.GetTextPoint() as double[]); + + if (pt[0] < leftMostValue) + { + leftMostValue = pt[0]; + leftMost = note; + } + + var txt = note.GetText(); + + if (txt.ToUpper().Contains("UP")) + upCount++; + else + dnCount++; + } + + Print(string.Format("Found {0} bends, {1} UP, {2} DOWN", notes.Count(), upCount, dnCount), Color.Blue); + + if (dnCount == upCount && leftMost != null) + return !leftMost.GetText().Contains("UP"); + + return dnCount > upCount; + } + + private string DrawingTemplatePath + { + get { return Path.Combine(Application.StartupPath, "Templates", "Blank.drwdot"); } + } + + private DrawingDoc CreateDrawing() + { + return sldWorks.NewDocument( + DrawingTemplatePath, + (int)swDwgPaperSizes_e.swDwgPaperDsize, + 1, + 1) as DrawingDoc; + } + + private List GetBomTables(DrawingDoc drawing) + { + var model = drawing as ModelDoc2; + + return model.GetAllFeaturesByTypeName("BomFeat") + .Select(f => f.GetSpecificFeature2() as BomFeature) + .Select(f => (f.GetTableAnnotations() as Array)?.Cast().FirstOrDefault()) + .ToList(); + } + + private List GetItems(BomTableAnnotation bom) + { + var items = new List(); + + var table = bom as TableAnnotation; + + var itemNumColumnFound = FindItemNumberColumn(bom as TableAnnotation); + + if (itemNumColumnFound == null) + { + Print("Error: Item number column not found."); + return null; + } + else + { + Print("Item numbers are in the " + Helper.GetNumWithSuffix(itemNumColumnFound.Value + 1) + " column."); + } + + var isBOMPartsOnly = bom.BomFeature.TableType == (int)swBomType_e.swBomType_PartsOnly; + + for (int rowIndex = 0; rowIndex < table.RowCount; rowIndex++) + { + if (table.RowHidden[rowIndex] == true) + continue; + + var bomComponents = isBOMPartsOnly ? + ((Array)bom.GetComponents2(rowIndex, bom.BomFeature.Configuration))?.Cast() : + ((Array)bom.GetComponents(rowIndex))?.Cast(); + + if (bomComponents == null) + continue; + + var distinctComponents = bomComponents + .GroupBy(c => c.ReferencedConfiguration) + .Select(group => group.First()); + + var itemNumber = table.Text[rowIndex, itemNumColumnFound.Value].PadLeft(2, '0'); + var rev = 'A'; + + if (distinctComponents.Count() > 1) + { + foreach (var comp in distinctComponents) + { + items.Add(new Item + { + Name = itemNumber + rev++, + Component = comp + }); + } + } + else + { + items.Add(new Item + { + Name = itemNumber, + Component = distinctComponents.First() + }); + } + } + + return items; + } + + private List GetItems(AssemblyDoc assembly, bool topLevel) + { + var list = new List(); + + assembly.ResolveAllLightWeightComponents(false); + + var assemblyComponents = ((Array)assembly.GetComponents(topLevel)) + .Cast() + .Where(c => !c.IsHidden(true)); + + var componentGroups = assemblyComponents + .GroupBy(c => c.GetTitle() + c.ReferencedConfiguration); + + foreach (var group in componentGroups) + { + var component = group.First(); + + var name = component.ReferencedConfiguration.ToLower() == "default" ? + component.GetTitle() : + string.Format("{0} [{1}]", component.GetTitle(), component.ReferencedConfiguration); + + list.Add(new Item + { + Name = name, + Quantity = group.Count(), + Component = component + }); + } + + return list; + } + + private void button2_Click(object sender, EventArgs e) + { + + } + } + + public static class Helper + { + public static Feature GetFeatureByTypeName(this ModelDoc2 model, string featureName) + { + var feature = model.FirstFeature() as Feature; + + while (feature != null) + { + if (feature.GetTypeName() == featureName) + return feature; + + feature = feature.GetNextFeature() as Feature; + } + + return feature; + } + + public static List GetAllFeaturesByTypeName(this ModelDoc2 model, string featureName) + { + var feature = model.FirstFeature() as Feature; + var list = new List(); + + while (feature != null) + { + if (feature.GetTypeName() == featureName) + list.Add(feature); + + feature = feature.GetNextFeature() as Feature; + } + + return list; + } + + public static bool HasFlatPattern(this ModelDoc2 model) + { + return model.GetBendState() != (int)swSMBendState_e.swSMBendStateNone; + } + + public static bool IsSheetMetal(this ModelDoc2 model) + { + if (model is PartDoc == false) + return false; + + if (model.HasFlatPattern() == false) + return false; + + return true; + } + + public static bool IsPart(this ModelDoc2 model) + { + return model is PartDoc; + } + + public static bool IsDrawing(this ModelDoc2 model) + { + return model is DrawingDoc; + } + + public static bool IsAssembly(this ModelDoc2 model) + { + return model is AssemblyDoc; + } + + public static string GetTitle(this Component2 component) + { + var model = component.GetModelDoc2() as ModelDoc2; + return model.GetTitle(); + } + + public static void AppendText(this RichTextBox box, string text, Color color) + { + box.SelectionStart = box.TextLength; + box.SelectionLength = 0; + + box.SelectionColor = color; + box.AppendText(text); + box.SelectionColor = box.ForeColor; + } + + public static string ToReadableFormat(this TimeSpan ts) + { + var s = new StringBuilder(); + + if (ts.TotalHours >= 1) + { + var hrs = ts.Hours + ts.Days * 24.0; + + s.Append(string.Format("{0}hrs ", hrs)); + s.Append(string.Format("{0}min ", ts.Minutes)); + s.Append(string.Format("{0}sec", ts.Seconds)); + } + else if (ts.TotalMinutes >= 1) + { + s.Append(string.Format("{0}min ", ts.Minutes)); + s.Append(string.Format("{0}sec", ts.Seconds)); + } + else + { + s.Append(string.Format("{0} seconds", ts.Seconds)); + } + + return s.ToString(); + } + + public static string GetNumWithSuffix(int i) + { + if (i >= 11 && i <= 13) + return i.ToString() + "th"; + + var j = i % 10; + + switch (j) + { + case 1: return i.ToString() + "st"; + case 2: return i.ToString() + "nd"; + case 3: return i.ToString() + "rd"; + default: return i.ToString() + "th"; + } + } + } + + public class Item + { + public string Name { get; set; } + + public int Quantity { get; set; } + + public Component2 Component { get; set; } + } +} diff --git a/ExportDXF/Forms/MainForm.resx b/ExportDXF/Forms/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/ExportDXF/Forms/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ExportDXF/Program.cs b/ExportDXF/Program.cs new file mode 100644 index 0000000..12da93b --- /dev/null +++ b/ExportDXF/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace ExportDXF +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Forms.MainForm()); + } + } +} diff --git a/ExportDXF/Properties/AssemblyInfo.cs b/ExportDXF/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c56f72e --- /dev/null +++ b/ExportDXF/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ExportDXF")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ExportDXF")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05f21d73-fd31-4e77-8d9b-41c86d4d8305")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ExportDXF/Properties/Resources.Designer.cs b/ExportDXF/Properties/Resources.Designer.cs new file mode 100644 index 0000000..431c9de --- /dev/null +++ b/ExportDXF/Properties/Resources.Designer.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ExportDXF.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExportDXF.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap edit_alt { + get { + object obj = ResourceManager.GetObject("edit_alt", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap play { + get { + object obj = ResourceManager.GetObject("play", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap stop_alt { + get { + object obj = ResourceManager.GetObject("stop_alt", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/ExportDXF/Properties/Resources.resx b/ExportDXF/Properties/Resources.resx new file mode 100644 index 0000000..1eae97b --- /dev/null +++ b/ExportDXF/Properties/Resources.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\edit_alt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\play.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\stop_alt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/ExportDXF/Properties/Settings.Designer.cs b/ExportDXF/Properties/Settings.Designer.cs new file mode 100644 index 0000000..b72cffc --- /dev/null +++ b/ExportDXF/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ExportDXF.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ExportDXF/Properties/Settings.settings b/ExportDXF/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/ExportDXF/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ExportDXF/Resources/edit_alt.png b/ExportDXF/Resources/edit_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..6117f96791493344dcbfe7d53e147d53393645ce GIT binary patch literal 1330 zcmV-21Z zZA@EL7=RCJvMn*X&0yjme;N5<=AybA#R2bvKC5Qv|kr{vJCKDmFbl@n^man!@J_;=@rM$lHxwoaIh4!L1d2(-W&-=d5 zIrpA(?`4d(CthYOzm>5f15*|Cv&Y4o>?KVb%hP?sJ}awbLRk$H_1l2|36Ydmvlm`G z&XV6AdyW@of{~LV7}!Cvhdrgf#@^I6vBJ^|tVmzGy+DMBC<_#oRI%6J$V^foqYeuj z*d9bB8ZuDg7E1I!tM2R&^|cO69!QcAwZ1mJ7-a>W5{c|@xd0Y@n~BCC69$1J4#Lx# z>!3b&9;r(R3J_~zX-#G^jYQHC+23&i~A0m>UrmY9omOH@O95(QW7BnzD5J)*f0Ac=h%6MWn`3r)s& z60!Hh(0w!f)n^FP(9#}XLR-m>9(#3*#Nl+7qrS*;HT5c-dI6N+H{gB+68HWw!(A-Q z`Fnux8=BjrXNO*1Cybj&Ih-a@2Aad~aJ zv~tD~5K%zTR?7l)uY6h*(m1edQ|4M~`3)ubgm zu7DUJ;P?43sW0J36g1nw=U;=hwOIUqe;9eO3M4JCiajEzXNe`OIAT8V#UYd@N6H2_-G|t;?#z;97jQ}-XT5`kU;v(*sIFyK3#N(WXu^lBoYO{b_ zj+1h@l?zbd{QNvDEG&efa|9jdG>pbbTp2iPYE;QV#zed5WgA#l#lg<};9P@vQ4bZ zYAPYti7C*uo8b{GoLV{v7jBL5Sjv@9K-eNMjXky5Y@CUSi7=5;@sZlu4;~*M|4&d3 z%0)S)+$2yHD{xj@!Oif`Hhgh_`tO@z#5@``{JVj2P%g?TVs257HA*XE1+sEaaRD?; zLtH!nUm}wEC`t6eBIk0c%WKo9Mv<-}R^aHdS7ZT60^i+QV!Z literal 0 HcmV?d00001 diff --git a/ExportDXF/Resources/play.png b/ExportDXF/Resources/play.png new file mode 100644 index 0000000000000000000000000000000000000000..991db6f7cac0fa3603cdba44256c99cdce293fd0 GIT binary patch literal 1134 zcmV-!1d;oRP)Cbymmm9S9!5SFs!SqT<_#gjGgiVksy1#BDMk5YZ6yqf z6r#&%s!h+6+KLG85_wAkVx@Qs3AHgQ24n`Qfm=_etJAlN1(P_%Bw8({fv;*`LF+^V zx~7cC=-9C&qhx~V>a?xGbmBCV_{|+OtRfDDCkeEN>S2vGqbI7xov04IQ6dx76WTcR=!+UK7&Rl~)_dzq z6s91ce^>*{qwBa$=zP?O?%5_-XPXIHj^^c>ZPtLD9otq*yvPd3QxIsGRG?#8&0?DV z6XuyZ{5@R{3kO}BXEZR))WSSnhwd3I-Z8$pv~4Sx8uq)YQxIsHs6t!#8cTav4r5pW zV?>FY5fz7$tw;iQx#~Ps^q9*XIj&RuCVW+ zw1pJdpb}GoaLNK2zYLARVl)JQ#b3eS&=i!RIr#e;XpO!`F@)qe-1AZ53EGyjfcn8j z)CDe}HgF!Az|W|kC?FK#I!8SVsRasgBUp)Jz1fNO$2KU%+fx1`toEIU(tj2T|M%>y z@}Gm+FD2x2NKr#(?PLj#-aVKIkCXF64lnPOr|}1eeC%5^ zj2Gib&w*9pq8#2fqAR1{q0Ezu63>??^&CT)Hy7oeuTbtijtcJyX#OpLq-XE?;e2ex zB_k&xb4yU{K7>o|!vqOrqY_*m{T%ACA8@EUlgIFN1TMLb?i9iRE*{!yK@H#XI6zXJRL}qj%0-n3G(k} z;;cObQZkp0$+>}SNbP%YX5f9uhL0f2^7eALi1%(l8~TEre%=x|oDS|{LU@4$g=iNx*F1%1YBwhyvjT?Gk+_->NXTm>&`h^g z(v3w@vy<8`;ldLm`EsgYo+Ui@WG<(4JfZ9Pe+J?cevz0_QUCw|07*qoM6N<$f;>(M AssI20 literal 0 HcmV?d00001 diff --git a/ExportDXF/Resources/stop_alt.png b/ExportDXF/Resources/stop_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..a48c24017e55206b09db26ba5e633ce1ae2d07df GIT binary patch literal 1602 zcmV-I2EF--P)t8ifP1kWOo2InVCe2F5yo3&>;*CiK$t3Xx0um^TcN8xzqT&jofV%7o znimuWHBh`?7gG?$$jmgSemCRnoX+#TpS!XwyNfY%=6m*ipXZ$OJnw$rw*&?G_FY@%T02OT0cc9?tt$;e2o%&WBBK{@o1cKP?Ip zKfKAk1}#T&J8Z(s*xlkOalpNc!0%^)KY0Dq0X(<{{M7(FY~+>k{d%=`mpS(?X*F&W zon0opekaIyOt4!G63d$G{dQ92-Z{#5f)W)-EaELRdiywYkFe$tYkww3jN3$))+V&$$k5NGjrh!O zfQExW{Vw3zUZ9aCnn>JS!w&0|Sj!n5r_@?=trBmf__ck&)!mE_YFus;p)M0vF<{c& z*p0?;mw5bGz)=pIF99xEfh&x!(!_Ndx=}?VoXRa4xmBy9My=i8lp1LC7m7P*{E}61 zFcwaiiBRpf)*5#i(C>59PaO%IW6_B`;N&LYY!PsQM3>7rjXflI<(d5m*BYUS{I8RWtdL?jl4N$X=#r%AFD@|=D zsf}Hc{K`-4iW8~dry#Mc$=(G!b9bnkI*Qk>C)bbUTt)7Dh=%^KYRAAa7VKXLRAvEH ztAS&=Bw+`2o7oLJIzuDpO4$+3oVV++sWsV?oVr5RSXj#js@X{8a-d?7#@)t1rl*0! zbh|4Z*qh0sr7Y$&s?F?z#%f4tAYL5fOQUFPogwr@kvO_dd#fcn|vGO}|bfb`9Jr zlyic1PSTn}t^}ZHI=PnwV8BMlmdQZ=RG@G=P|V_OB(bs!+kAFI;xc|m%4ulVVg-rI z7pgtUvC{N*))XfKTV?|>tY@iVfiwkI^a26-SqbcT8O6JlO z4Q)?Tka!#GiYZ#eoGr6ejfL-!yjWlzxpJa3Za)T$aBgPD%ZCHmqkz@pXl4S@mQqD3Z~Pc@n#!p&SaVjaA5rRcq#Gl_R-QvwW1|SQHK{7^HEFM*GhJ zF<|D~FFg!M`vREvC14uD;-MrV(UK9sGLmMECbr7IT6NhN)WN5H4~G zw=VB`HyB*6W5*%G{WbgZ)D)&3q#P!fPgzE|Mh{s>R0x|F`vBG@}G6}bdFp{M6 zJY(JlCUym)yQw&)J23ej4|G?1(Qg5hx~iOc!!-_X;)VK;p&-8|J||HM&o=6HV9d+F zxL1f*f$^`khOEh+gux1lL%c)Zmt2>)F+lM^OxTSE-p2-YeH?p!=Jlz?+cRNPw`hm{HPdhF zj*EMm@b%xYKa@VL_>(5&IbrfZW;^iA%LqXHKgg?o=l7(5vj6}907*qoM6N<$f|{`j A_y7O^ literal 0 HcmV?d00001 diff --git a/ExportDXF/Templates/Blank.drwdot b/ExportDXF/Templates/Blank.drwdot new file mode 100644 index 0000000000000000000000000000000000000000..56fc40dcd94f912f3548fc7af86bcf0511d89b60 GIT binary patch literal 21115 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 vo}@9c