# 列印輸出攔截補完工作報告

> 日期: 2026-04-11  
> 時間: 13:14:59  
> 目標: HBSTK (Harbour GTWVT Console Mode)

---

## 1. 工作背景

先前已建立 `OpenSpool/CloseSpool` → `SpoolOpenToFile/SpoolCloseAndPrint` 機制，
將所有列印輸出攔截至 `RPT日期時間毫秒.PRN` 唯一檔案。

但 `FILE_OUTPUT` 分支（使用者選擇輸出至檔案）漏未納入攔截，
仍直接操作 `SET(_SET_PRINTFILE, ...)` 繞過 spool 機制。

---

## 2. 修改一：compat/print_spool.prg

### 2-1 新增靜態變數

```prg
STATIC s_cCurrentPrnFile := ""  // 儲存目前列印工作的 PRN 路徑
```

### 2-2 修改 SpoolOpenToFile()

| 舊 | 新 |
|----|----|
| `LOCAL cOutFile := hb_DirBase() + "output.prn"` | `LOCAL cOutFile` |
| 刪除舊 output.prn | 移除（檔名唯一不需刪除） |
| 固定寫入 output.prn | `cOutFile := GenPrnFileName()` → `s_cCurrentPrnFile := cOutFile` |

### 2-3 修改 SpoolCloseAndPrint()

| 舊 | 新 |
|----|----|
| `LOCAL cOutFile := hb_DirBase() + "output.prn"` | `LOCAL cOutFile := s_cCurrentPrnFile` |
| `PrnToPdf(..., "output.pdf", ...)` | `PrnToPdf(..., hb_FNameDir(cOutFile)+hb_FNameName(cOutFile)+".PDF", ...)` |

### 2-4 新增 GenPrnFileName()

```prg
STATIC FUNCTION GenPrnFileName()
   LOCAL cDate := DToS( Date() )                         // YYYYMMDD
   LOCAL cTime := StrTran( Time(), ":", "" )             // HHMMSS
   LOCAL nMs   := hb_MilliSeconds() % 1000               // 0~999
   LOCAL cMs   := PadL( AllTrim( Str( nMs ) ), 3, "0" ) // 3 digits
   RETURN hb_DirBase() + "RPT" + cDate + cTime + cMs + ".PRN"
```

**輸出範例：** `RPT20260411131459123.PRN`

---

## 3. 修改二：source/ 各報表模組

### 3-1 修改模式

**FILE_OUTPUT 分支（舊）：**
```prg
cPrinter := SET(_SET_PRINTFILE, (MEMVAR->cLocRpt+"\"+cFileName), .F.)
lPrinter := SET(_SET_PRINTER, .T.)
lConsole := SET(_SET_CONSOLE, .F.)
// ... 報表輸出 ...
SET(_SET_CONSOLE, lConsole)
SET(_SET_PRINTER, lPrinter)
SET(_SET_PRINTFILE, "")
```

**FILE_OUTPUT 分支（新）：**
```prg
OpenSpool( cFileName, , @cPrintPort )
lPrinter := SET(_SET_PRINTER, .T.)
lConsole := SET(_SET_CONSOLE, .F.)
// ... 報表輸出 ...
SET(_SET_CONSOLE, lConsole)
SET(_SET_PRINTER, lPrinter)
CloseSpool( cFileName, , cPrintPort )
```

### 3-2 修改檔案清單

| 檔案 | 替換次數 | 說明 |
|------|---------|------|
| P123.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P221.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P241.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P25.PRG  | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P246.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P27.PRG  | 3 | FILE_OUTPUT OpenSpool/CloseSpool（含額外分支） |
| P36.PRG  | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P351.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P355.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P373.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P415.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P424.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P46.PRG  | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| P47.PRG  | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| REPORT.PRG | 2 | FILE_OUTPUT OpenSpool/CloseSpool |
| PRINT.PRG  | 2 | nOutput=2 分支的 OpenSpool 補上 |
| P14.PRG    | 4 | PrnMail: OpenSpool + CloseSpool + 注解 COPY FILE |
| P413.PRG   | 4 | PrnTrustBill: OpenSpool + CloseSpool + 注解 COPY FILE |

**共計：18 個檔案，39 處修改**

---

## 4. 未修改（確認無需處理）

| 位置 | 原因 |
|------|------|
| P27.PRG:391 | LPT 埠設定（非檔案輸出），在 PRINTER_OUTPUT 的系統旗標判斷內 |
| PRINT.PRG:45 | LPT 埠設定，後面立即被 OpenSpool 覆蓋，無影響 |

---

## 5. 備份檔案

所有修改前均已建立備份（副檔名 `.bak_fileout`），位於 `source/` 目錄。

---

## 6. 最終效果

- **所有列印輸出路徑** 均經過 `OpenSpool → SpoolOpenToFile → GenPrnFileName`
- **每次列印** 產生唯一的 `RPT日期時間毫秒.PRN` 檔案，不再覆蓋
- **PDF 轉換** 也使用相同的唯一檔名（同名 `.PDF`）
- **歷史列印記錄** 完整保留在 build/ 目錄
