diff --git a/.gitignore b/.gitignore
index 00902a3..38233a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+# Stray Windows redirect artifact
+/nul
+
# User-specific files
*.suo
*.user
diff --git a/ExportDXF/ExportDXF.csproj b/ExportDXF/ExportDXF.csproj
index 405ba86..0d6545a 100644
--- a/ExportDXF/ExportDXF.csproj
+++ b/ExportDXF/ExportDXF.csproj
@@ -37,6 +37,9 @@
Always
+
+ Always
+
diff --git a/ExportDXF/Services/DxfExportService.cs b/ExportDXF/Services/DxfExportService.cs
index b7615b3..aab8a6c 100644
--- a/ExportDXF/Services/DxfExportService.cs
+++ b/ExportDXF/Services/DxfExportService.cs
@@ -130,7 +130,7 @@ namespace ExportDXF.Services
ExportContext context,
string tempDir,
string outputFolder,
- Dictionary existingTemplates,
+ Dictionary existingTemplates,
List bomItems)
{
LogProgress(context, "Active document is a Part");
@@ -159,7 +159,7 @@ namespace ExportDXF.Services
ExportContext context,
string tempDir,
string outputFolder,
- Dictionary existingTemplates,
+ Dictionary existingTemplates,
List bomItems)
{
LogProgress(context, "Active document is an Assembly");
@@ -200,7 +200,7 @@ namespace ExportDXF.Services
ExportContext context,
string tempDir,
string outputFolder,
- Dictionary existingTemplates,
+ Dictionary existingTemplates,
List bomItems)
{
LogProgress(context, "Active document is a Drawing");
@@ -294,7 +294,7 @@ namespace ExportDXF.Services
string tempDir,
string outputFolder,
ExportContext context,
- Dictionary existingTemplates,
+ Dictionary existingTemplates,
List bomItems)
{
int successCount = 0;
@@ -362,7 +362,7 @@ namespace ExportDXF.Services
Item item,
ExportContext context,
string outputFolder,
- Dictionary existingTemplates,
+ Dictionary existingTemplates,
BomItem bomItem)
{
var baseName = FilenameTemplateParser.Evaluate(context.FilenameTemplate, item);
@@ -377,15 +377,15 @@ namespace ExportDXF.Services
if (existing.ContentHash == contentHash)
{
// Unchanged — skip file write, keep existing
- dxfFileName = existing.FileName;
revision = existing.Revision;
+ dxfFileName = GetRevisionFileName(baseName, revision);
LogProgress(context, $"Unchanged: {dxfFileName}", LogLevel.Info, item.PartName);
_logFileService.LogInfo($"Unchanged: {dxfFileName}");
bomItem.CutTemplate = new CutTemplate
{
- DxfFilePath = dxfFileName,
+ DxfFilePath = Path.GetFileNameWithoutExtension(dxfFileName),
ContentHash = contentHash,
Revision = revision,
Thickness = item.Thickness > 0 ? item.Thickness : (double?)null,
@@ -402,7 +402,7 @@ namespace ExportDXF.Services
dxfFileName = GetRevisionFileName(baseName, revision);
LogProgress(context, $"Updated: {dxfFileName} (Rev{revision})", LogLevel.Info, item.PartName);
- _logFileService.LogInfo($"Updated: {dxfFileName} (was {existing.FileName})");
+ _logFileService.LogInfo($"Updated: {dxfFileName}");
}
}
else
diff --git a/ExportDXF/Services/ExcelExportService.cs b/ExportDXF/Services/ExcelExportService.cs
index d097b49..29cf599 100644
--- a/ExportDXF/Services/ExcelExportService.cs
+++ b/ExportDXF/Services/ExcelExportService.cs
@@ -1,6 +1,8 @@
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection;
using ClosedXML.Excel;
using ExportDXF.Models;
@@ -8,14 +10,18 @@ namespace ExportDXF.Services
{
public class ExcelExportService
{
+ private static readonly string TemplatePath = Path.Combine(
+ Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ "Templates",
+ "BOM Template.xlsx");
///
/// Reads existing Cut Templates from an xlsx file to compare content hashes.
/// Returns empty dictionary if file doesn't exist or has no Cut Templates sheet.
- /// Key = Item #, Value = (ContentHash, Revision, FileName)
+ /// Key = Item #, Value = (ContentHash, Revision)
///
- public Dictionary ReadExistingCutTemplates(string xlsxPath)
+ public Dictionary ReadExistingCutTemplates(string xlsxPath)
{
- var result = new Dictionary();
+ var result = new Dictionary();
if (!File.Exists(xlsxPath))
return result;
@@ -49,12 +55,9 @@ namespace ExportDXF.Services
var revision = headers.ContainsKey("Revision")
? ws.Cell(row, headers["Revision"]).GetValue()
: 1;
- var fileName = headers.ContainsKey("File Name")
- ? ws.Cell(row, headers["File Name"]).GetString()
- : "";
if (!string.IsNullOrEmpty(itemNo))
- result[itemNo] = (hash, revision, fileName);
+ result[itemNo] = (hash, revision);
}
}
@@ -71,9 +74,12 @@ namespace ExportDXF.Services
List> rawBomTable,
List bomItems)
{
- using (var workbook = File.Exists(xlsxPath)
- ? new XLWorkbook(xlsxPath)
- : new XLWorkbook())
+ if (!File.Exists(TemplatePath))
+ throw new FileNotFoundException("Excel template not found.", TemplatePath);
+
+ File.Copy(TemplatePath, xlsxPath, overwrite: true);
+
+ using (var workbook = new XLWorkbook(xlsxPath))
{
WriteBomSheet(workbook, rawBomTable);
WriteCutTemplatesSheet(workbook, bomItems);
@@ -86,10 +92,9 @@ namespace ExportDXF.Services
if (rawBomTable == null || rawBomTable.Count == 0)
return;
- if (workbook.TryGetWorksheet("BOM", out _))
- workbook.Worksheets.Delete("BOM");
+ var sheet = GetOrCreateSheet(workbook, "BOM");
+ sheet.Clear();
- var sheet = workbook.Worksheets.Add("BOM");
var columns = rawBomTable[0].Keys.ToList();
for (int col = 0; col < columns.Count; col++)
@@ -110,30 +115,34 @@ namespace ExportDXF.Services
private void WriteCutTemplatesSheet(XLWorkbook workbook, List bomItems)
{
- if (workbook.TryGetWorksheet("Cut Templates", out _))
- workbook.Worksheets.Delete("Cut Templates");
+ var sheet = GetOrCreateSheet(workbook, "Cut Templates");
- var sheet = workbook.Worksheets.Add("Cut Templates");
-
- var headers = new[] { "Item #", "File Name", "Revision", "Thickness", "K-Factor", "Bend Radius", "Content Hash" };
- for (int col = 0; col < headers.Length; col++)
- sheet.Cell(1, col + 1).Value = headers[col];
+ // Clear data rows only (preserve template headers/formatting in row 1)
+ var lastRow = sheet.LastRowUsed()?.RowNumber() ?? 1;
+ if (lastRow > 1)
+ sheet.Range(2, 1, lastRow, sheet.LastColumnUsed()?.ColumnNumber() ?? 1).Clear();
int row = 2;
foreach (var item in bomItems.Where(b => b.CutTemplate != null).OrderBy(b => b.ItemNo))
{
var ct = item.CutTemplate;
sheet.Cell(row, 1).Value = item.ItemNo;
- sheet.Cell(row, 2).Value = ct.DxfFilePath;
- sheet.Cell(row, 3).Value = ct.Revision;
- sheet.Cell(row, 4).Value = ct.Thickness ?? 0;
- sheet.Cell(row, 5).Value = ct.KFactor ?? 0;
- sheet.Cell(row, 6).Value = ct.DefaultBendRadius ?? 0;
- sheet.Cell(row, 7).Value = ct.ContentHash ?? "";
+ sheet.Cell(row, 2).Value = ct.Revision;
+ sheet.Cell(row, 3).Value = ct.Thickness ?? 0;
+ sheet.Cell(row, 4).Value = ct.KFactor ?? 0;
+ sheet.Cell(row, 5).Value = ct.DefaultBendRadius ?? 0;
+ sheet.Cell(row, 6).Value = ct.ContentHash ?? "";
row++;
}
sheet.Columns().AdjustToContents();
}
+
+ private IXLWorksheet GetOrCreateSheet(XLWorkbook workbook, string name)
+ {
+ if (workbook.TryGetWorksheet(name, out var sheet))
+ return sheet;
+ return workbook.Worksheets.Add(name);
+ }
}
}
diff --git a/ExportDXF/Templates/BOM Template.xlsx b/ExportDXF/Templates/BOM Template.xlsx
new file mode 100644
index 0000000..105d730
Binary files /dev/null and b/ExportDXF/Templates/BOM Template.xlsx differ