|
| 1 | +using Tender.Core.Models; |
| 2 | + |
| 3 | +namespace Tender.Desktop.Services; |
| 4 | + |
| 5 | +/// <summary> |
| 6 | +/// 每一份 .xlsm 範本(ISMS / ESG 等)有自己的 cellXfs 樣式表與 worksheet rel id, |
| 7 | +/// 此類保存「重寫 sheet1 / sheet2 時需要用到」的全部變數,避免每個匯出器重複寫一遍。 |
| 8 | +/// |
| 9 | +/// 樣式索引必須對應目標 .xlsm 的 styles.xml 中既有 cellXfs,否則開檔會出現「已修復的記錄」或樣式錯亂。 |
| 10 | +/// </summary> |
| 11 | +internal sealed class XlsmTemplateProfile |
| 12 | +{ |
| 13 | + public required string TemplateRelativePath { get; init; } |
| 14 | + |
| 15 | + // ---- sheet1「全部資料」---- |
| 16 | + public required string Sheet1SheetFormatPr { get; init; } |
| 17 | + public required string Sheet1Cols { get; init; } |
| 18 | + public required string Sheet1DrawingRelId { get; init; } |
| 19 | + public required string Sheet1PrinterRelId { get; init; } |
| 20 | + public required int Sheet1HeaderStyle { get; init; } |
| 21 | + public required int Sheet1HeaderJStyle { get; init; } |
| 22 | + public required int Sheet1HeaderHStyle { get; init; } |
| 23 | + public required int Sheet1DataBStyle { get; init; } |
| 24 | + public required int Sheet1DataCStyle { get; init; } |
| 25 | + public required int Sheet1DataDStyle { get; init; } |
| 26 | + public required int Sheet1DataEStyle { get; init; } |
| 27 | + public required int Sheet1DataFStyle { get; init; } |
| 28 | + public required int Sheet1DataGStyle { get; init; } |
| 29 | + public required int Sheet1DataHStyle { get; init; } |
| 30 | + public required int Sheet1DataIStyle { get; init; } |
| 31 | + public required int Sheet1DataJStyle { get; init; } |
| 32 | + |
| 33 | + // ---- sheet2「篩選」---- |
| 34 | + public required string Sheet2DrawingRelId { get; init; } |
| 35 | + public required string Sheet2PrinterRelId { get; init; } |
| 36 | + public required int Sheet2ColumnStyle { get; init; } |
| 37 | + public required int Sheet2DataBStyle { get; init; } |
| 38 | + |
| 39 | + // ---- 1150511_ISMS標案.xlsm ---- |
| 40 | + // styles.xml: cellXfs count=18; |
| 41 | + // sheet1.xml.rels: 印表 rId1637 / 繪圖 rId1638; |
| 42 | + // sheet2.xml.rels: 印表 rId1 / 繪圖 rId2。 |
| 43 | + public static XlsmTemplateProfile Isms { get; } = new() |
| 44 | + { |
| 45 | + TemplateRelativePath = "Templates/tender-template-isms.xlsm", |
| 46 | + Sheet1SheetFormatPr = "<sheetFormatPr defaultRowHeight=\"16.5\"/>", |
| 47 | + Sheet1Cols = |
| 48 | + "<cols>" + |
| 49 | + "<col min=\"1\" max=\"1\" width=\"2.625\" style=\"6\" customWidth=\"1\"/>" + |
| 50 | + "<col min=\"2\" max=\"2\" width=\"45.5\" style=\"1\" customWidth=\"1\"/>" + |
| 51 | + "<col min=\"3\" max=\"3\" width=\"9\" style=\"6\"/>" + |
| 52 | + "<col min=\"4\" max=\"4\" width=\"10.5\" style=\"1\" customWidth=\"1\"/>" + |
| 53 | + "<col min=\"5\" max=\"5\" width=\"9.625\" style=\"1\" customWidth=\"1\"/>" + |
| 54 | + "<col min=\"6\" max=\"7\" width=\"10\" style=\"1\" customWidth=\"1\"/>" + |
| 55 | + "<col min=\"8\" max=\"8\" width=\"9.875\" style=\"1\" customWidth=\"1\"/>" + |
| 56 | + "<col min=\"9\" max=\"9\" width=\"10.125\" style=\"1\" customWidth=\"1\"/>" + |
| 57 | + "<col min=\"10\" max=\"16384\" width=\"9\" style=\"1\"/>" + |
| 58 | + "</cols>", |
| 59 | + Sheet1DrawingRelId = "rId1638", |
| 60 | + Sheet1PrinterRelId = "rId1637", |
| 61 | + Sheet1HeaderStyle = 9, |
| 62 | + Sheet1HeaderJStyle = 10, |
| 63 | + Sheet1HeaderHStyle = 9, |
| 64 | + Sheet1DataBStyle = 17, |
| 65 | + Sheet1DataCStyle = 12, |
| 66 | + Sheet1DataDStyle = 13, |
| 67 | + Sheet1DataEStyle = 14, |
| 68 | + Sheet1DataFStyle = 14, |
| 69 | + Sheet1DataGStyle = 14, |
| 70 | + Sheet1DataHStyle = 15, |
| 71 | + Sheet1DataIStyle = 13, |
| 72 | + Sheet1DataJStyle = 16, |
| 73 | + Sheet2DrawingRelId = "rId2", |
| 74 | + Sheet2PrinterRelId = "rId1", |
| 75 | + Sheet2ColumnStyle = 8, |
| 76 | + Sheet2DataBStyle = 1, |
| 77 | + }; |
| 78 | + |
| 79 | + // ---- 1150511_ESG標案.xlsm ---- |
| 80 | + // styles.xml: cellXfs count=25; |
| 81 | + // sheet1.xml.rels: 印表 rId1637 / 繪圖 rId1638(與 ISMS 相同); |
| 82 | + // sheet2.xml.rels: 印表 rId3 / 繪圖 rId4。 |
| 83 | + public static XlsmTemplateProfile Esg { get; } = new() |
| 84 | + { |
| 85 | + TemplateRelativePath = "Templates/tender-template-esg.xlsm", |
| 86 | + Sheet1SheetFormatPr = "<sheetFormatPr defaultRowHeight=\"16.5\"/>", |
| 87 | + Sheet1Cols = |
| 88 | + "<cols>" + |
| 89 | + "<col min=\"1\" max=\"1\" width=\"2.625\" style=\"10\" customWidth=\"1\"/>" + |
| 90 | + "<col min=\"2\" max=\"2\" width=\"45.5\" style=\"1\" customWidth=\"1\"/>" + |
| 91 | + "<col min=\"3\" max=\"3\" width=\"9\" style=\"10\"/>" + |
| 92 | + "<col min=\"4\" max=\"4\" width=\"10.5\" style=\"1\" customWidth=\"1\"/>" + |
| 93 | + "<col min=\"5\" max=\"5\" width=\"9.625\" style=\"1\" customWidth=\"1\"/>" + |
| 94 | + "<col min=\"6\" max=\"7\" width=\"10\" style=\"1\" customWidth=\"1\"/>" + |
| 95 | + "<col min=\"8\" max=\"8\" width=\"9.875\" style=\"1\" customWidth=\"1\"/>" + |
| 96 | + "<col min=\"9\" max=\"9\" width=\"10.125\" style=\"1\" customWidth=\"1\"/>" + |
| 97 | + "<col min=\"10\" max=\"16384\" width=\"9\" style=\"1\"/>" + |
| 98 | + "</cols>", |
| 99 | + Sheet1DrawingRelId = "rId1638", |
| 100 | + Sheet1PrinterRelId = "rId1637", |
| 101 | + Sheet1HeaderStyle = 14, |
| 102 | + Sheet1HeaderJStyle = 15, |
| 103 | + Sheet1HeaderHStyle = 14, |
| 104 | + Sheet1DataBStyle = 24, |
| 105 | + Sheet1DataCStyle = 6, |
| 106 | + Sheet1DataDStyle = 7, |
| 107 | + Sheet1DataEStyle = 9, |
| 108 | + Sheet1DataFStyle = 9, |
| 109 | + Sheet1DataGStyle = 9, |
| 110 | + Sheet1DataHStyle = 8, |
| 111 | + Sheet1DataIStyle = 7, |
| 112 | + Sheet1DataJStyle = 16, |
| 113 | + Sheet2DrawingRelId = "rId4", |
| 114 | + Sheet2PrinterRelId = "rId3", |
| 115 | + Sheet2ColumnStyle = 12, |
| 116 | + Sheet2DataBStyle = 24, |
| 117 | + }; |
| 118 | +} |
| 119 | + |
| 120 | +internal sealed class IsmsTemplateXlsmExporter : IIsmsXlsmExporter |
| 121 | +{ |
| 122 | + private readonly ProfiledTemplateXlsmExporter _inner = new(XlsmTemplateProfile.Isms); |
| 123 | + |
| 124 | + public Task ExportAsync( |
| 125 | + IReadOnlyList<TenderItem> allItems, |
| 126 | + IReadOnlyList<TenderItem> filteredItems, |
| 127 | + string savePath, |
| 128 | + CancellationToken ct = default) |
| 129 | + => _inner.ExportAsync(allItems, filteredItems, savePath, ct); |
| 130 | +} |
| 131 | + |
| 132 | +internal sealed class EsgTemplateXlsmExporter : IEsgXlsmExporter |
| 133 | +{ |
| 134 | + private readonly ProfiledTemplateXlsmExporter _inner = new(XlsmTemplateProfile.Esg); |
| 135 | + |
| 136 | + public Task ExportAsync( |
| 137 | + IReadOnlyList<TenderItem> allItems, |
| 138 | + IReadOnlyList<TenderItem> filteredItems, |
| 139 | + string savePath, |
| 140 | + CancellationToken ct = default) |
| 141 | + => _inner.ExportAsync(allItems, filteredItems, savePath, ct); |
| 142 | +} |
0 commit comments