refactor: remove Excel export functionality

Removed BomExcelExporter service, BomExcelSettings class, BomTemplate.xlsx template, and EPPlus package dependency. This functionality is being replaced with direct API integration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-03 06:45:58 -05:00
parent 5cf7e1f1e5
commit 84f0196c97
4 changed files with 30 additions and 483 deletions

View File

@@ -103,6 +103,12 @@
<Compile Include="Extensions\TimeSpanExtensions.cs" /> <Compile Include="Extensions\TimeSpanExtensions.cs" />
<Compile Include="Extensions\UIExtensions.cs" /> <Compile Include="Extensions\UIExtensions.cs" />
<Compile Include="Extensions\UnitConversionExtensions.cs" /> <Compile Include="Extensions\UnitConversionExtensions.cs" />
<Compile Include="Forms\DrawingSelectionForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\DrawingSelectionForm.Designer.cs">
<DependentUpon>DrawingSelectionForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\MainForm.cs"> <Compile Include="Forms\MainForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@@ -116,11 +122,11 @@
<Compile Include="Forms\ViewFlipDeciderComboboxItem.cs" /> <Compile Include="Forms\ViewFlipDeciderComboboxItem.cs" />
<Compile Include="Models\DocumentType.cs" /> <Compile Include="Models\DocumentType.cs" />
<Compile Include="Models\ExportContext.cs" /> <Compile Include="Models\ExportContext.cs" />
<Compile Include="Models\BomItem.cs" />
<Compile Include="Models\Item.cs" /> <Compile Include="Models\Item.cs" />
<Compile Include="Models\LogEvent.cs" />
<Compile Include="Models\SolidWorksDocument.cs" /> <Compile Include="Models\SolidWorksDocument.cs" />
<Compile Include="Services\BomExcelExporter.cs" />
<Compile Include="Services\BomExtractor.cs" /> <Compile Include="Services\BomExtractor.cs" />
<Compile Include="Services\BomExcelSettings.cs" />
<Compile Include="Services\DrawingExporter.cs" /> <Compile Include="Services\DrawingExporter.cs" />
<Compile Include="Services\DxfExportService.cs" /> <Compile Include="Services\DxfExportService.cs" />
<Compile Include="Services\CutFabApiClient.cs" /> <Compile Include="Services\CutFabApiClient.cs" />
@@ -137,6 +143,9 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewFlipDeciders\PreferUpViewFlipDecider.cs" /> <Compile Include="ViewFlipDeciders\PreferUpViewFlipDecider.cs" />
<Compile Include="ViewFlipDeciders\ViewFlipDeciderFactory.cs" /> <Compile Include="ViewFlipDeciders\ViewFlipDeciderFactory.cs" />
<EmbeddedResource Include="Forms\DrawingSelectionForm.resx">
<DependentUpon>DrawingSelectionForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\MainForm.resx"> <EmbeddedResource Include="Forms\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@@ -163,9 +172,6 @@
<Content Include="Templates\Blank.drwdot"> <Content Include="Templates\Blank.drwdot">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Templates\BomTemplate.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Resources\edit_alt.png" /> <None Include="Resources\edit_alt.png" />
@@ -193,18 +199,31 @@
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="EPPlus">
<Version>4.5.3.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\EtchBendLines\EtchBendLines\EtchBendLines.csproj"> <ProjectReference Include="..\EtchBendLines\EtchBendLines\EtchBendLines.csproj">
<Project>{229c2fb9-6ad6-4a5d-b83a-d1146573d6f9}</Project> <Project>{229c2fb9-6ad6-4a5d-b83a-d1146573d6f9}</Project>
<Name>EtchBendLines</Name> <Name>EtchBendLines</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<COMReference Include="AcroPDFLib">
<Guid>{05BFD3F1-6319-4F30-B752-C7A22889BCC4}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="AxAcroPDFLib">
<Guid>{05BFD3F1-6319-4F30-B752-C7A22889BCC4}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>aximp</WrapperTool>
<Isolated>False</Isolated>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,408 +0,0 @@
using ExportDXF.Utilities;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
namespace ExportDXF.Services
{
/// <summary>
/// Service for creating BOM Excel files.
/// </summary>
public interface IBomExcelExporter
{
/// <summary>
/// Creates an Excel file containing the Bill of Materials.
/// </summary>
/// <param name="filepath">The full path where the Excel file will be saved.</param>
/// <param name="items">The list of items to include in the BOM.</param>
void CreateBOMExcelFile(string filepath, IList<Item> items);
}
/// <summary>
/// Service for creating Excel files containing Bill of Materials data.
/// </summary>
public class BomExcelExporter : IBomExcelExporter
{
private const string DEFAULT_TEMPLATE_FILENAME = "BomTemplate.xlsx";
private const string DEFAULT_SHEET_NAME = "Parts";
private const int HEADER_ROW = 1;
private const int DATA_START_ROW = 2;
private const double COLUMN_PADDING = 2.0;
private const int MAX_COLUMN_WIDTH = 50;
private readonly string _templatePath;
private readonly BomExcelSettings _settings;
public BomExcelExporter() : this(GetDefaultTemplatePath(), new BomExcelSettings())
{
}
public BomExcelExporter(string templatePath) : this(templatePath, new BomExcelSettings())
{
}
public BomExcelExporter(string templatePath, BomExcelSettings settings)
{
if (string.IsNullOrWhiteSpace(templatePath))
throw new ArgumentException("Template path cannot be null or empty.", nameof(templatePath));
_templatePath = templatePath;
_settings = settings ?? new BomExcelSettings();
// Set EPPlus license context (required for newer versions)
//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
}
/// <summary>
/// Creates an Excel file containing the Bill of Materials.
/// </summary>
public void CreateBOMExcelFile(string filepath, IList<Item> items)
{
if (string.IsNullOrWhiteSpace(filepath))
throw new ArgumentException("Filepath cannot be null or empty.", nameof(filepath));
if (items == null)
throw new ArgumentNullException(nameof(items));
ValidateAndPrepareFile(filepath);
using (var package = new ExcelPackage(new FileInfo(filepath)))
{
var worksheet = GetOrCreateWorksheet(package);
PopulateWorksheet(worksheet, items);
FormatWorksheet(worksheet);
package.Save();
}
}
#region Worksheet Management
private ExcelWorksheet GetOrCreateWorksheet(ExcelPackage package)
{
var worksheet = package.Workbook.Worksheets[DEFAULT_SHEET_NAME];
if (worksheet == null)
{
if (_settings.CreateWorksheetIfMissing)
{
worksheet = package.Workbook.Worksheets.Add(DEFAULT_SHEET_NAME);
CreateDefaultHeaders(worksheet);
}
else
{
var availableSheets = string.Join(", ",
package.Workbook.Worksheets.Select(ws => ws.Name));
throw new InvalidOperationException(
$"Worksheet '{DEFAULT_SHEET_NAME}' not found in template. " +
$"Available sheets: {availableSheets}");
}
}
return worksheet;
}
private void CreateDefaultHeaders(ExcelWorksheet worksheet)
{
var headers = new[]
{
"Item No", "File Name", "Qty", "Description", "Part Name",
"Configuration", "Thickness", "Material", "K-Factor", "Bend Radius"
};
for (int i = 0; i < headers.Length; i++)
{
var cell = worksheet.Cells[HEADER_ROW, i + 1];
cell.Value = headers[i];
if (_settings.FormatHeaders)
{
cell.Style.Font.Bold = true;
cell.Style.Fill.PatternType = ExcelFillStyle.Solid;
cell.Style.Fill.BackgroundColor.SetColor(Color.LightGray);
}
}
}
#endregion
#region Data Population
private void PopulateWorksheet(ExcelWorksheet worksheet, IList<Item> items)
{
var filteredItems = _settings.SkipItemsWithoutFiles
? items.Where(i => !string.IsNullOrEmpty(i.FileName)).ToList()
: items.ToList();
for (int i = 0; i < filteredItems.Count; i++)
{
var item = filteredItems[i];
var row = DATA_START_ROW + i;
WriteItemToRow(worksheet, row, item);
}
// Add summary information if enabled
if (_settings.AddSummary && filteredItems.Count > 0)
{
AddSummarySection(worksheet, filteredItems, DATA_START_ROW + filteredItems.Count + 2);
}
}
private void WriteItemToRow(ExcelWorksheet worksheet, int row, Item item)
{
int col = 1;
// Item No
worksheet.Cells[row, col++].Value = FormatItemNumber(item.ItemNo);
// File Name
worksheet.Cells[row, col++].Value = item.FileName;
// Quantity
worksheet.Cells[row, col++].Value = item.Quantity;
// Description
worksheet.Cells[row, col++].Value = CleanDescription(item.Description);
// Part Name
worksheet.Cells[row, col++].Value = item.PartName;
// Configuration
worksheet.Cells[row, col++].Value = item.Configuration;
// Thickness (only if > 0)
worksheet.Cells[row, col++].Value = GetFormattedNumericValue(item.Thickness, _settings.ThicknessDecimalPlaces);
// Material
worksheet.Cells[row, col++].Value = item.Material;
// K-Factor (only if > 0)
worksheet.Cells[row, col++].Value = GetFormattedNumericValue(item.KFactor, _settings.KFactorDecimalPlaces);
// Bend Radius (only if > 0)
worksheet.Cells[row, col++].Value = GetFormattedNumericValue(item.BendRadius, _settings.BendRadiusDecimalPlaces);
// Apply row formatting
if (_settings.AlternateRowColors && row % 2 == 0)
{
var rowRange = worksheet.Cells[row, 1, row, col - 1];
rowRange.Style.Fill.PatternType = ExcelFillStyle.Solid;
rowRange.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(240, 240, 240));
}
}
private void AddSummarySection(ExcelWorksheet worksheet, IList<Item> items, int startRow)
{
worksheet.Cells[startRow, 1].Value = "SUMMARY";
worksheet.Cells[startRow, 1].Style.Font.Bold = true;
worksheet.Cells[startRow, 1].Style.Font.Size = 12;
startRow += 2;
// Total items
worksheet.Cells[startRow, 1].Value = "Total Items:";
worksheet.Cells[startRow, 2].Value = items.Count;
// Total quantity
var totalQty = items.Sum(i => i.Quantity);
worksheet.Cells[startRow + 1, 1].Value = "Total Quantity:";
worksheet.Cells[startRow + 1, 2].Value = totalQty;
// Unique materials
var uniqueMaterials = items.Where(i => !string.IsNullOrEmpty(i.Material))
.Select(i => i.Material)
.Distinct()
.Count();
worksheet.Cells[startRow + 2, 1].Value = "Unique Materials:";
worksheet.Cells[startRow + 2, 2].Value = uniqueMaterials;
// Thickness range
var thicknesses = items.Where(i => i.Thickness > 0).Select(i => i.Thickness).ToList();
if (thicknesses.Any())
{
worksheet.Cells[startRow + 3, 1].Value = "Thickness Range:";
worksheet.Cells[startRow + 3, 2].Value = $"{thicknesses.Min():F1} - {thicknesses.Max():F1} mm";
}
}
#endregion
#region Data Formatting
private string FormatItemNumber(string itemNo)
{
if (string.IsNullOrWhiteSpace(itemNo))
return string.Empty;
// Try to parse as number and pad with zeros if it's a simple number
if (int.TryParse(itemNo, out int number))
{
return number.ToString().PadLeft(_settings.ItemNumberPadding, '0');
}
return itemNo;
}
private string CleanDescription(string description)
{
if (string.IsNullOrWhiteSpace(description))
return string.Empty;
// Remove any remaining XML tags that might have been missed
description = TextHelper.RemoveXmlTags(description);
// Trim and normalize whitespace
return System.Text.RegularExpressions.Regex.Replace(description.Trim(), @"\s+", " ");
}
private object GetFormattedNumericValue(double value, int decimalPlaces)
{
if (value <= 0)
return null;
return Math.Round(value, decimalPlaces);
}
#endregion
#region Worksheet Formatting
private void FormatWorksheet(ExcelWorksheet worksheet)
{
if (worksheet.Dimension == null)
return;
// Auto-fit columns with limits
for (int col = 1; col <= worksheet.Dimension.Columns; col++)
{
worksheet.Column(col).AutoFit();
// Special handling for Description column (assuming it's column 4)
if (col == 4) // Description column
{
worksheet.Column(col).Width = Math.Max(worksheet.Column(col).Width, 30); // Minimum 30 units
if (worksheet.Column(col).Width > 50) // Maximum 50 units
worksheet.Column(col).Width = 50;
}
else if (worksheet.Column(col).Width > MAX_COLUMN_WIDTH)
{
worksheet.Column(col).Width = MAX_COLUMN_WIDTH;
}
else
{
worksheet.Column(col).Width += COLUMN_PADDING;
}
}
// Add borders if enabled
if (_settings.AddBorders)
{
var dataRange = worksheet.Cells[HEADER_ROW, 1, worksheet.Dimension.End.Row, worksheet.Dimension.End.Column];
dataRange.Style.Border.Top.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Left.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Right.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
}
// Format numeric columns
FormatNumericColumns(worksheet);
// Freeze header row if enabled
if (_settings.FreezeHeaderRow)
{
worksheet.View.FreezePanes(DATA_START_ROW, 1);
}
}
private void FormatNumericColumns(ExcelWorksheet worksheet)
{
if (worksheet.Dimension == null)
return;
var lastRow = worksheet.Dimension.End.Row;
// Format quantity column (assuming it's column 3)
if (worksheet.Dimension.Columns >= 3)
{
var qtyRange = worksheet.Cells[DATA_START_ROW, 3, lastRow, 3];
qtyRange.Style.Numberformat.Format = "0";
qtyRange.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
}
// Format thickness column (assuming it's column 7)
if (worksheet.Dimension.Columns >= 7)
{
var thicknessRange = worksheet.Cells[DATA_START_ROW, 7, lastRow, 7];
thicknessRange.Style.Numberformat.Format = $"0.{new string('0', _settings.ThicknessDecimalPlaces)}";
thicknessRange.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
}
}
#endregion
#region File Management
private void ValidateAndPrepareFile(string filepath)
{
var directory = Path.GetDirectoryName(filepath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (UseTemplate())
{
CopyTemplateToDestination(filepath);
}
else if (File.Exists(filepath))
{
File.Delete(filepath); // Remove existing file to start fresh
}
}
private bool UseTemplate()
{
return !string.IsNullOrEmpty(_templatePath) && File.Exists(_templatePath);
}
private void CopyTemplateToDestination(string filepath)
{
if (!File.Exists(_templatePath))
{
throw new FileNotFoundException(
$"BOM template file not found at: {_templatePath}. " +
"Either provide a valid template or enable CreateWorksheetIfMissing.",
_templatePath);
}
try
{
File.Copy(_templatePath, filepath, overwrite: true);
}
catch (Exception ex)
{
throw new IOException($"Failed to copy template to {filepath}: {ex.Message}", ex);
}
}
private static string GetDefaultTemplatePath()
{
return Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Templates",
DEFAULT_TEMPLATE_FILENAME);
}
#endregion
}
}

View File

@@ -1,64 +0,0 @@
namespace ExportDXF.Services
{
/// <summary>
/// Configuration settings for BOM Excel export.
/// </summary>
public class BomExcelSettings
{
/// <summary>
/// Create the worksheet if it doesn't exist in the template.
/// </summary>
public bool CreateWorksheetIfMissing { get; set; } = true;
/// <summary>
/// Skip items that don't have an associated DXF file.
/// </summary>
public bool SkipItemsWithoutFiles { get; set; } = false;
/// <summary>
/// Add summary section with totals and statistics.
/// </summary>
public bool AddSummary { get; set; } = false;
/// <summary>
/// Format header row with bold text and background color.
/// </summary>
public bool FormatHeaders { get; set; } = false;
/// <summary>
/// Add borders around all cells.
/// </summary>
public bool AddBorders { get; set; } = false;
/// <summary>
/// Freeze the header row for easier scrolling.
/// </summary>
public bool FreezeHeaderRow { get; set; } = true;
/// <summary>
/// Alternate row background colors for easier reading.
/// </summary>
public bool AlternateRowColors { get; set; } = true;
/// <summary>
/// Number of decimal places for thickness values.
/// </summary>
public int ThicknessDecimalPlaces { get; set; } = 4;
/// <summary>
/// Number of decimal places for K-Factor values.
/// </summary>
public int KFactorDecimalPlaces { get; set; } = 3;
/// <summary>
/// Number of decimal places for bend radius values.
/// </summary>
public int BendRadiusDecimalPlaces { get; set; } = 3;
/// <summary>
/// Minimum number of digits for item numbers (pad with zeros).
/// </summary>
public int ItemNumberPadding { get; set; } = 2;
}
}

Binary file not shown.