using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; namespace DrillTools { /// /// 生成 CAM350 风格的钻孔使用报告。 /// internal static class DrillUsageReportExporter { public static string GenerateReport(IReadOnlyList tools, string layerName, DateTime exportTime) { if (tools == null) throw new ArgumentNullException(nameof(tools)); var rows = tools.Select((tool, index) => CreateRow(tool, index + 1)).ToList(); var report = new StringBuilder(); AppendHeader(report, layerName, exportTime); AppendRows(report, rows); AppendTotals(report, rows); return report.ToString(); } private static ReportRow CreateRow(ToolItem tool, int order) { // 当前导出顺序与 Tool Ref 相同;未来如有独立钻孔执行顺序可拆分维护。 return new ReportRow( order, tool.ToolNumber, FormatDiameter(tool.Diameter), order, tool.RegularHoles, tool.SlotHoles, tool.TotalHoles); } private static void AppendHeader(StringBuilder report, string layerName, DateTime exportTime) { report.AppendLine("Project file name: "); report.AppendLine($"Date: {FormatDate(exportTime)}"); report.AppendLine($"Table: DrillTable_1 Layer: {layerName}"); report.AppendLine("Drill Usage:"); report.AppendLine("Table # Tool Ref Tool # Size Exp Ord Plated Hits Unplated Hits Total Hits"); report.AppendLine("======= ======== ====== ==== ======= =========== ============= =========="); } private static void AppendRows(StringBuilder report, IReadOnlyList rows) { // Column widths and gaps match the header/separator layout exactly. // Separator sections: [0..6]=7 [9..16]=8 [20..25]=6 [37..40]=4 [52..58]=7 [61..71]=11 [74..86]=13 [89..98]=10 // Gaps between sections: 2sp 3sp 11sp 11sp 2sp 2sp 2sp foreach (var row in rows) { report.AppendLine(string.Format( CultureInfo.InvariantCulture, "{0,-7} {1,-8} {2,-6} {3,-4} {4,-7} {5,-11} {6,-13} {7,-10}", 1, row.ToolRef, row.ToolNumber, row.Size, row.ExportOrder, row.PlatedHits, row.UnplatedHits, row.TotalHits)); } } private static void AppendTotals(StringBuilder report, IReadOnlyList rows) { report.AppendLine("=========================================================== =========== ============= =========="); report.AppendLine(string.Format( CultureInfo.InvariantCulture, "{0,59} {1,-11} {2,-13} {3,-10}", "Totals:", rows.Sum(row => row.PlatedHits), rows.Sum(row => row.UnplatedHits), rows.Sum(row => row.TotalHits))); } private static string FormatDate(DateTime value) { return $"{value:HH:mm:ss} {value.Year}年{value.Month}月{value.Day}日"; } private static string FormatDiameter(double value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } private sealed record ReportRow( int ToolRef, int ToolNumber, string Size, int ExportOrder, int PlatedHits, int UnplatedHits, int TotalHits); } }