diff --git a/ExportDXF/Services/DxfExportService.cs b/ExportDXF/Services/DxfExportService.cs
index 5f8a67b..b7615b3 100644
--- a/ExportDXF/Services/DxfExportService.cs
+++ b/ExportDXF/Services/DxfExportService.cs
@@ -1,9 +1,7 @@
-using ExportDXF.ApiClient;
using ExportDXF.Extensions;
using ExportDXF.ItemExtractors;
using ExportDXF.Models;
using ExportDXF.Utilities;
-using ExportDXF;
using SolidWorks.Interop.sldworks;
using System;
using System.Collections.Generic;
@@ -15,42 +13,34 @@ namespace ExportDXF.Services
{
public interface IDxfExportService
{
- ///
- /// Exports the document specified in the context to DXF format.
- ///
- /// The export context containing all necessary information.
Task ExportAsync(ExportContext context);
}
- ///
- /// Service responsible for orchestrating the export of SolidWorks documents to DXF format.
- /// Files are generated locally in a temp directory, then uploaded to the API for storage and versioning.
- ///
public class DxfExportService : IDxfExportService
{
private readonly ISolidWorksService _solidWorksService;
private readonly IBomExtractor _bomExtractor;
private readonly IPartExporter _partExporter;
private readonly IDrawingExporter _drawingExporter;
- private readonly IFabWorksApiClient _apiClient;
+ private readonly ExcelExportService _excelExportService;
+ private readonly LogFileService _logFileService;
public DxfExportService(
ISolidWorksService solidWorksService,
IBomExtractor bomExtractor,
IPartExporter partExporter,
IDrawingExporter drawingExporter,
- IFabWorksApiClient apiClient)
+ ExcelExportService excelExportService,
+ LogFileService logFileService)
{
_solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService));
_bomExtractor = bomExtractor ?? throw new ArgumentNullException(nameof(bomExtractor));
_partExporter = partExporter ?? throw new ArgumentNullException(nameof(partExporter));
_drawingExporter = drawingExporter ?? throw new ArgumentNullException(nameof(drawingExporter));
- _apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
+ _excelExportService = excelExportService ?? throw new ArgumentNullException(nameof(excelExportService));
+ _logFileService = logFileService ?? throw new ArgumentNullException(nameof(logFileService));
}
- ///
- /// Exports the document specified in the context to DXF format.
- ///
public async Task ExportAsync(ExportContext context)
{
if (context == null)
@@ -59,6 +49,28 @@ namespace ExportDXF.Services
ValidateContext(context);
SetupExportContext(context);
+ var outputFolder = context.OutputFolder;
+ if (!Directory.Exists(outputFolder))
+ Directory.CreateDirectory(outputFolder);
+
+ var prefix = FilenameTemplateParser.GetPrefix(
+ context.FilenameTemplate,
+ context.ActiveDocument.Title);
+
+ var xlsxPath = Path.Combine(outputFolder, $"{prefix}.xlsx");
+ var logPath = Path.Combine(outputFolder, $"{prefix}.log");
+
+ _logFileService.StartExportLog(logPath);
+ _logFileService.LogInfo($"Export started: {context.ActiveDocument.FilePath}");
+ _logFileService.LogInfo($"Template: {context.FilenameTemplate}");
+ _logFileService.LogInfo($"Output: {outputFolder}");
+
+ // Read existing cut templates for revision comparison
+ var existingTemplates = _excelExportService.ReadExistingCutTemplates(xlsxPath);
+
+ var bomItems = new List();
+ List> rawBomTable = null;
+
var startTime = DateTime.Now;
var tempDir = CreateTempWorkDir();
@@ -66,26 +78,39 @@ namespace ExportDXF.Services
{
_solidWorksService.EnableUserControl(false);
- var drawingNumber = ParseDrawingNumber(context);
-
switch (context.ActiveDocument.DocumentType)
{
case DocumentType.Part:
- await ExportPartAsync(context, tempDir, drawingNumber);
+ await ExportPartAsync(context, tempDir, outputFolder, existingTemplates, bomItems);
break;
case DocumentType.Assembly:
- await ExportAssemblyAsync(context, tempDir, drawingNumber);
+ await ExportAssemblyAsync(context, tempDir, outputFolder, existingTemplates, bomItems);
break;
case DocumentType.Drawing:
- await ExportDrawingAsync(context, drawingNumber, tempDir);
+ rawBomTable = await ExportDrawingAsync(context, tempDir, outputFolder, existingTemplates, bomItems);
break;
default:
LogProgress(context, "Unknown document type.", LogLevel.Error);
break;
}
+
+ // Write Excel file
+ _excelExportService.Write(xlsxPath, rawBomTable, bomItems);
+ _logFileService.LogInfo($"Wrote {Path.GetFileName(xlsxPath)}");
+ LogProgress(context, $"Saved {Path.GetFileName(xlsxPath)}");
+ }
+ catch (OperationCanceledException)
+ {
+ _logFileService.LogWarning("Export cancelled by user");
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _logFileService.LogError($"Export failed: {ex.Message}");
+ throw;
}
finally
{
@@ -94,13 +119,19 @@ namespace ExportDXF.Services
CleanupTempDir(tempDir);
var duration = DateTime.Now - startTime;
+ _logFileService.LogInfo($"Run time: {duration.ToReadableFormat()}");
LogProgress(context, $"Run time: {duration.ToReadableFormat()}");
}
}
#region Export Methods by Document Type
- private async Task ExportPartAsync(ExportContext context, string tempDir, string drawingNumber)
+ private async Task ExportPartAsync(
+ ExportContext context,
+ string tempDir,
+ string outputFolder,
+ Dictionary existingTemplates,
+ List bomItems)
{
LogProgress(context, "Active document is a Part");
@@ -111,54 +142,25 @@ namespace ExportDXF.Services
return;
}
- var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
var item = _partExporter.ExportSinglePart(part, tempDir, context);
if (item != null)
{
- // Check if this part+config already has a BOM item for this drawing
- var existingItemNo = await FindExistingItemNoAsync(exportRecord?.Id, item.PartName, item.Configuration);
- item.ItemNo = existingItemNo ?? await GetNextItemNumberAsync(drawingNumber);
-
- var bomItem = new BomItem
- {
- ExportRecordId = exportRecord?.Id ?? 0,
- ItemNo = item.ItemNo,
- PartNo = item.FileName ?? item.PartName ?? "",
- SortOrder = 0,
- Qty = item.Quantity,
- TotalQty = item.Quantity,
- Description = item.Description ?? "",
- PartName = item.PartName ?? "",
- ConfigurationName = item.Configuration ?? "",
- Material = item.Material ?? ""
- };
-
- // Upload DXF to API and get stored path
- if (!string.IsNullOrEmpty(item.LocalTempPath))
- {
- var uploadResult = await UploadDxfAsync(item, context);
- if (uploadResult != null)
- {
- bomItem.CutTemplate = new CutTemplate
- {
- DxfFilePath = uploadResult.StoredFilePath,
- ContentHash = item.ContentHash,
- Thickness = item.Thickness > 0 ? item.Thickness : null,
- KFactor = item.KFactor > 0 ? item.KFactor : null,
- DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
- };
- }
- }
+ item.ItemNo = "1";
+ var bomItem = CreateBomItem(item);
+ PlaceDxfFile(item, context, outputFolder, existingTemplates, bomItem);
+ bomItems.Add(bomItem);
context.BomItemCallback?.Invoke(bomItem);
-
- if (exportRecord != null)
- await SaveBomItemAsync(exportRecord.Id, bomItem, context);
}
}
- private async Task ExportAssemblyAsync(ExportContext context, string tempDir, string drawingNumber)
+ private async Task ExportAssemblyAsync(
+ ExportContext context,
+ string tempDir,
+ string outputFolder,
+ Dictionary existingTemplates,
+ List bomItems)
{
LogProgress(context, "Active document is an Assembly");
LogProgress(context, "Fetching components...");
@@ -180,31 +182,26 @@ namespace ExportDXF.Services
LogProgress(context, $"Found {items.Count} item(s).");
- var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
-
- // Check existing BOM items and reuse item numbers, or assign new ones
- var nextNum = int.Parse(await GetNextItemNumberAsync(drawingNumber));
+ // Assign item numbers
+ int nextNum = 1;
foreach (var item in items)
{
if (string.IsNullOrWhiteSpace(item.ItemNo))
{
- var existingItemNo = await FindExistingItemNoAsync(exportRecord?.Id, item.PartName, item.Configuration);
- if (existingItemNo != null)
- {
- item.ItemNo = existingItemNo;
- }
- else
- {
- item.ItemNo = nextNum.ToString();
- nextNum++;
- }
+ item.ItemNo = nextNum.ToString();
+ nextNum++;
}
}
- await ExportItemsAsync(items, tempDir, context, exportRecord?.Id);
+ await ExportItemsAsync(items, tempDir, outputFolder, context, existingTemplates, bomItems);
}
- private async Task ExportDrawingAsync(ExportContext context, string drawingNumber, string tempDir)
+ private async Task>> ExportDrawingAsync(
+ ExportContext context,
+ string tempDir,
+ string outputFolder,
+ Dictionary existingTemplates,
+ List bomItems)
{
LogProgress(context, "Active document is a Drawing");
LogProgress(context, "Finding BOM tables...");
@@ -213,59 +210,35 @@ namespace ExportDXF.Services
if (drawing == null)
{
LogProgress(context, "Failed to get drawing document.", LogLevel.Error);
- return;
+ return null;
}
+ // Read raw BOM table for Excel output
+ var rawBomTable = new List>();
+ var bomTables = drawing.GetBomTables();
+ foreach (var table in bomTables)
+ {
+ var rows = RawBomTableReader.Read(table);
+ rawBomTable.AddRange(rows);
+ }
+
+ // Extract items for DXF export
var items = _bomExtractor.ExtractFromDrawing(drawing, context.ProgressCallback);
if (items == null || items.Count == 0)
{
LogProgress(context, "Error: Bill of materials not found.", LogLevel.Error);
- return;
+ return rawBomTable;
}
LogProgress(context, $"Found {items.Count} component(s)");
- // Export drawing to PDF in temp dir
- _drawingExporter.ExportToPdf(drawing, tempDir, context);
+ // Export drawing to PDF in output folder
+ _drawingExporter.ExportToPdf(drawing, outputFolder, context);
- // Create export record via API
- var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
+ await ExportItemsAsync(items, tempDir, outputFolder, context, existingTemplates, bomItems);
- // Upload PDF to API with versioning
- try
- {
- var pdfs = Directory.GetFiles(tempDir, "*.pdf");
- if (pdfs.Length > 0)
- {
- var pdfTempPath = pdfs[0];
- var pdfHash = ContentHasher.ComputeFileHash(pdfTempPath);
-
- var uploadResult = await _apiClient.UploadPdfAsync(
- pdfTempPath,
- context.Equipment,
- context.DrawingNo,
- pdfHash,
- exportRecord?.Id);
-
- if (uploadResult != null)
- {
- if (uploadResult.WasUnchanged)
- LogProgress(context, $"PDF unchanged: {uploadResult.FileName}", LogLevel.Info);
- else if (uploadResult.IsNewFile)
- LogProgress(context, $"Saved PDF: {uploadResult.FileName}", LogLevel.Info);
- else
- LogProgress(context, $"PDF updated: {uploadResult.FileName}", LogLevel.Info);
- }
- }
- }
- catch (Exception ex)
- {
- LogProgress(context, $"PDF upload error: {ex.Message}", LogLevel.Error);
- }
-
- // Export parts to DXF and save BOM items
- await ExportItemsAsync(items, tempDir, context, exportRecord?.Id);
+ return rawBomTable;
}
#endregion
@@ -274,17 +247,12 @@ namespace ExportDXF.Services
private void SetupExportContext(ExportContext context)
{
- // Set up SolidWorks application reference
context.SolidWorksApp = _solidWorksService.GetNativeSldWorks();
if (context.SolidWorksApp == null)
- {
throw new InvalidOperationException("SolidWorks service is not connected.");
- }
- // Set up drawing template path
context.TemplateDrawing = null;
-
LogProgress(context, "Export context initialized");
}
@@ -292,13 +260,11 @@ namespace ExportDXF.Services
{
try
{
- // Clean up template drawing if it was created
context.CleanupTemplateDrawing();
}
catch (Exception ex)
{
LogProgress(context, $"Warning: Failed to cleanup template drawing: {ex.Message}", LogLevel.Warning);
- // Don't throw - this is cleanup code
}
}
@@ -314,7 +280,6 @@ namespace ExportDXF.Services
{
TopLevelOnly = false
};
-
return extractor.GetItems();
}
catch (Exception ex)
@@ -324,10 +289,17 @@ namespace ExportDXF.Services
}
}
- private async Task ExportItemsAsync(List- items, string tempDir, ExportContext context, int? exportRecordId = null)
+ private async Task ExportItemsAsync(
+ List
- items,
+ string tempDir,
+ string outputFolder,
+ ExportContext context,
+ Dictionary existingTemplates,
+ List bomItems)
{
int successCount = 0;
int skippedCount = 0;
+ int unchangedCount = 0;
int failureCount = 0;
int sortOrder = 0;
@@ -341,215 +313,150 @@ namespace ExportDXF.Services
try
{
- // PartExporter will handle template drawing creation through context
_partExporter.ExportItem(item, tempDir, context);
- // Always create BomItem for every item (sheet metal or not)
- var bomItem = new BomItem
- {
- ExportRecordId = exportRecordId ?? 0,
- ItemNo = item.ItemNo ?? "",
- PartNo = item.FileName ?? item.PartName ?? "",
- SortOrder = sortOrder++,
- Qty = item.Quantity,
- TotalQty = item.Quantity,
- Description = item.Description ?? "",
- PartName = item.PartName ?? "",
- ConfigurationName = item.Configuration ?? "",
- Material = item.Material ?? ""
- };
+ var bomItem = CreateBomItem(item);
+ bomItem.SortOrder = sortOrder++;
- // Only upload and create CutTemplate if DXF was exported successfully
if (!string.IsNullOrEmpty(item.LocalTempPath))
{
- successCount++;
-
- var uploadResult = await UploadDxfAsync(item, context);
- if (uploadResult != null)
- {
- bomItem.CutTemplate = new CutTemplate
- {
- DxfFilePath = uploadResult.StoredFilePath,
- ContentHash = item.ContentHash,
- Thickness = item.Thickness > 0 ? item.Thickness : null,
- KFactor = item.KFactor > 0 ? item.KFactor : null,
- DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
- };
- }
+ var wasPlaced = PlaceDxfFile(item, context, outputFolder, existingTemplates, bomItem);
+ if (wasPlaced)
+ successCount++;
+ else
+ unchangedCount++;
}
else
{
skippedCount++;
}
- // Add to UI
+ bomItems.Add(bomItem);
context.BomItemCallback?.Invoke(bomItem);
-
- // Save BOM item via API if we have an export record
- if (exportRecordId.HasValue)
- {
- await SaveBomItemAsync(exportRecordId.Value, bomItem, context);
- }
}
catch (Exception ex)
{
LogProgress(context, $"Error exporting item {item.ItemNo}: {ex.Message}", LogLevel.Error);
+ _logFileService.LogError($"Item {item.ItemNo}: {ex.Message}");
failureCount++;
}
}
- var summary = $"Export complete: {successCount} exported, {skippedCount} skipped";
+ var summary = $"Export complete: {successCount} exported";
+ if (unchangedCount > 0)
+ summary += $", {unchangedCount} unchanged";
+ if (skippedCount > 0)
+ summary += $", {skippedCount} skipped (non-sheet-metal)";
if (failureCount > 0)
summary += $", {failureCount} failed";
+
LogProgress(context, summary, failureCount > 0 ? LogLevel.Warning : LogLevel.Info);
-
- if (exportRecordId.HasValue)
- {
- LogProgress(context, $"BOM items saved (ExportRecord ID: {exportRecordId.Value})", LogLevel.Info);
- }
+ _logFileService.LogInfo(summary);
}
- #endregion
-
- #region File Upload
-
- private async Task UploadDxfAsync(Item item, ExportContext context)
+ ///
+ /// Places a DXF file in the output folder with revision tracking.
+ /// Returns true if a new file was written, false if unchanged.
+ ///
+ private bool PlaceDxfFile(
+ Item item,
+ ExportContext context,
+ string outputFolder,
+ Dictionary existingTemplates,
+ BomItem bomItem)
{
- try
+ var baseName = FilenameTemplateParser.Evaluate(context.FilenameTemplate, item);
+ var contentHash = item.ContentHash;
+
+ int revision = 1;
+ string dxfFileName;
+
+ // Check existing templates for revision comparison
+ if (existingTemplates.TryGetValue(item.ItemNo, out var existing))
{
- var result = await _apiClient.UploadDxfAsync(
- item.LocalTempPath,
- context.Equipment,
- context.DrawingNo,
- item.ItemNo,
- item.ContentHash);
-
- if (result.WasUnchanged)
- LogProgress(context, $"DXF unchanged: {result.FileName}", LogLevel.Info);
- else if (result.IsNewFile)
- LogProgress(context, $"Exported: {result.FileName}", LogLevel.Info);
- else
- LogProgress(context, $"DXF updated: {result.FileName}", LogLevel.Info);
-
- return result;
- }
- catch (Exception ex)
- {
- LogProgress(context, $"DXF upload failed for {item.FileName}: {ex.Message}", LogLevel.Warning);
- return null;
- }
- }
-
- #endregion
-
- #region API Helpers
-
- private async Task CreateExportRecordAsync(ExportContext context, string drawingNumber)
- {
- try
- {
- var dto = await _apiClient.CreateExportAsync(
- drawingNumber ?? context.ActiveDocument.Title,
- context.Equipment ?? "",
- context.DrawingNo ?? "",
- context.ActiveDocument.FilePath,
- "", // Output folder is now managed by the API
- context.Title);
-
- var record = new ExportRecord
+ if (existing.ContentHash == contentHash)
{
- Id = dto.Id,
- DrawingNumber = dto.DrawingNumber,
- EquipmentNo = dto.EquipmentNo,
- DrawingNo = dto.DrawingNo,
- SourceFilePath = dto.SourceFilePath,
- OutputFolder = dto.OutputFolder,
- ExportedAt = dto.ExportedAt,
- ExportedBy = dto.ExportedBy
- };
+ // Unchanged — skip file write, keep existing
+ dxfFileName = existing.FileName;
+ revision = existing.Revision;
- LogProgress(context, $"Created export record (ID: {record.Id})", LogLevel.Info);
- return record;
- }
- catch (Exception ex)
- {
- LogProgress(context, $"API error creating export record: {ex.Message}", LogLevel.Error);
- return null;
- }
- }
+ LogProgress(context, $"Unchanged: {dxfFileName}", LogLevel.Info, item.PartName);
+ _logFileService.LogInfo($"Unchanged: {dxfFileName}");
- private async Task FindExistingItemNoAsync(int? exportRecordId, string partName, string configurationName)
- {
- if (!exportRecordId.HasValue)
- return null;
-
- try
- {
- var existing = await _apiClient.FindExistingBomItemAsync(exportRecordId.Value, partName, configurationName);
- return existing?.ItemNo;
- }
- catch
- {
- return null;
- }
- }
-
- private async Task GetNextItemNumberAsync(string drawingNumber)
- {
- if (string.IsNullOrEmpty(drawingNumber))
- return "1";
-
- try
- {
- return await _apiClient.GetNextItemNumberAsync(drawingNumber);
- }
- catch
- {
- return "1";
- }
- }
-
- private async Task SaveBomItemAsync(int exportRecordId, BomItem bomItem, ExportContext context)
- {
- try
- {
- var apiBomItem = new ApiBomItem
- {
- ItemNo = bomItem.ItemNo,
- PartNo = bomItem.PartNo,
- SortOrder = bomItem.SortOrder,
- Qty = bomItem.Qty,
- TotalQty = bomItem.TotalQty,
- Description = bomItem.Description,
- PartName = bomItem.PartName,
- ConfigurationName = bomItem.ConfigurationName,
- Material = bomItem.Material
- };
-
- if (bomItem.CutTemplate != null)
- {
- apiBomItem.CutTemplate = new ApiCutTemplate
+ bomItem.CutTemplate = new CutTemplate
{
- DxfFilePath = bomItem.CutTemplate.DxfFilePath,
- ContentHash = bomItem.CutTemplate.ContentHash,
- Thickness = bomItem.CutTemplate.Thickness,
- KFactor = bomItem.CutTemplate.KFactor,
- DefaultBendRadius = bomItem.CutTemplate.DefaultBendRadius
+ DxfFilePath = dxfFileName,
+ ContentHash = contentHash,
+ Revision = revision,
+ Thickness = item.Thickness > 0 ? item.Thickness : (double?)null,
+ KFactor = item.KFactor > 0 ? item.KFactor : (double?)null,
+ DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : (double?)null
};
- }
- await _apiClient.CreateBomItemAsync(exportRecordId, apiBomItem);
+ return false;
+ }
+ else
+ {
+ // Changed — increment revision
+ revision = existing.Revision + 1;
+ dxfFileName = GetRevisionFileName(baseName, revision);
+
+ LogProgress(context, $"Updated: {dxfFileName} (Rev{revision})", LogLevel.Info, item.PartName);
+ _logFileService.LogInfo($"Updated: {dxfFileName} (was {existing.FileName})");
+ }
}
- catch (Exception ex)
+ else
{
- LogProgress(context, $"API error saving BOM item: {ex.Message}", LogLevel.Error);
+ // New item
+ dxfFileName = $"{baseName}.dxf";
+ LogProgress(context, $"Exported: {dxfFileName}", LogLevel.Info, item.PartName);
+ _logFileService.LogInfo($"Exported: {dxfFileName}");
}
+
+ // Copy from temp to output
+ var destPath = Path.Combine(outputFolder, dxfFileName);
+ File.Copy(item.LocalTempPath, destPath, overwrite: true);
+
+ bomItem.CutTemplate = new CutTemplate
+ {
+ DxfFilePath = Path.GetFileNameWithoutExtension(dxfFileName),
+ ContentHash = contentHash,
+ Revision = revision,
+ Thickness = item.Thickness > 0 ? item.Thickness : (double?)null,
+ KFactor = item.KFactor > 0 ? item.KFactor : (double?)null,
+ DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : (double?)null
+ };
+
+ return true;
+ }
+
+ private BomItem CreateBomItem(Item item)
+ {
+ return new BomItem
+ {
+ ItemNo = item.ItemNo ?? "",
+ PartNo = item.FileName ?? item.PartName ?? "",
+ SortOrder = 0,
+ Qty = item.Quantity,
+ TotalQty = item.Quantity,
+ Description = item.Description ?? "",
+ PartName = item.PartName ?? "",
+ ConfigurationName = item.Configuration ?? "",
+ Material = item.Material ?? ""
+ };
}
#endregion
#region Helper Methods
+ private string GetRevisionFileName(string baseName, int revision)
+ {
+ if (revision <= 1)
+ return $"{baseName}.dxf";
+ return $"{baseName} Rev{revision}.dxf";
+ }
+
private string CreateTempWorkDir()
{
var path = Path.Combine(Path.GetTempPath(), "ExportDXF-" + Guid.NewGuid().ToString("N"));
@@ -570,27 +477,6 @@ namespace ExportDXF.Services
}
}
- private string ParseDrawingNumber(ExportContext context)
- {
- // Use explicit Equipment/DrawingNo from the UI when available
- if (!string.IsNullOrWhiteSpace(context?.Equipment))
- {
- return !string.IsNullOrWhiteSpace(context?.DrawingNo)
- ? $"{context.Equipment} {context.DrawingNo}"
- : context.Equipment;
- }
-
- // Fallback: parse from prefix or document title
- var candidate = context?.FilePrefix;
- var info = string.IsNullOrWhiteSpace(candidate) ? null : DrawingInfo.Parse(candidate);
- if (info == null)
- {
- var title = context?.ActiveDocument?.Title;
- info = string.IsNullOrWhiteSpace(title) ? null : DrawingInfo.Parse(title);
- }
- return info?.ToString();
- }
-
private void ValidateContext(ExportContext context)
{
if (context.ActiveDocument == null)
@@ -598,6 +484,12 @@ namespace ExportDXF.Services
if (context.ProgressCallback == null)
throw new ArgumentException("ProgressCallback cannot be null.", nameof(context));
+
+ if (string.IsNullOrWhiteSpace(context.FilenameTemplate))
+ throw new ArgumentException("FilenameTemplate cannot be null or empty.", nameof(context));
+
+ if (string.IsNullOrWhiteSpace(context.OutputFolder))
+ throw new ArgumentException("OutputFolder cannot be null or empty.", nameof(context));
}
private void LogProgress(ExportContext context, string message, LogLevel level = LogLevel.Info, string file = null)
diff --git a/ExportDXF/Services/PartExporter.cs b/ExportDXF/Services/PartExporter.cs
index 789e9bf..b5a5645 100644
--- a/ExportDXF/Services/PartExporter.cs
+++ b/ExportDXF/Services/PartExporter.cs
@@ -54,7 +54,7 @@ namespace ExportDXF.Services
try
{
- var fileName = GetSinglePartFileName(model, context.FilePrefix);
+ var fileName = GetSinglePartFileName(model);
var savePath = Path.Combine(saveDirectory, fileName + ".dxf");
// Build result item with metadata
@@ -139,7 +139,7 @@ namespace ExportDXF.Services
EnrichItemWithMetadata(item, model, part);
- var fileName = GetItemFileName(item, context.FilePrefix);
+ var fileName = GetItemFileName(item);
var savePath = Path.Combine(saveDirectory, fileName + ".dxf");
var templateDrawing = context.GetOrCreateTemplateDrawing();
@@ -332,7 +332,7 @@ namespace ExportDXF.Services
}
}
- private string GetSinglePartFileName(ModelDoc2 model, string prefix)
+ private string GetSinglePartFileName(ModelDoc2 model)
{
var title = model.GetTitle().Replace(".SLDPRT", "");
var config = model.ConfigurationManager.ActiveConfiguration.Name;
@@ -341,17 +341,13 @@ namespace ExportDXF.Services
return isDefaultConfig ? title : $"{title} [{config}]";
}
- private string GetItemFileName(Item item, string prefix)
+ private string GetItemFileName(Item item)
{
if (string.IsNullOrWhiteSpace(item.ItemNo))
- return item.PartName;
+ return item.PartName ?? "unknown";
- prefix = prefix?.Replace("\"", "''") ?? string.Empty;
var num = item.ItemNo.PadLeft(2, '0');
- // Expected format: {DrawingNo} PT{ItemNo}
- return string.IsNullOrWhiteSpace(prefix)
- ? $"PT{num}"
- : $"{prefix} PT{num}";
+ return $"PT{num}";
}
private void LogExportFailure(Item item, ExportContext context)