📌如何在 Vue 3 應用中實現「篩選後」合併儲存格並匯出 Excel
一、文章摘要
在使用 Vue 3 開發複雜表格時,常會遇到需要「篩選」 +「匯出 Excel」的需求,而表格中的相同資料欄位需要以「合併儲存格」方式呈現。本篇將詳解如何修改原有的合併邏輯,讓程式能夠在使用者先做篩選後,再正確對應並合併儲存格,並最終輸出成 Excel 檔案。
二、背景與挑戰
-
基本需求
-
使用者在畫面上對表格做搜尋、篩選。
-
點擊「匯出 Excel」按鈕時,將篩選後的結果輸出。
-
輸出的表格中,相同 APS 計畫編號、客戶、週別等欄位,要自動合併儲存格,以維持易讀性。
-
-
舊版做法的問題
-
原本的
rowSpans及匯出邏輯都用「全部資料陣列」(mappedTableData.value)計算。 -
若使用者先篩選,只輸出部分列,儲存格合併仍依據「全部資料」計算,導致範圍錯誤或重複。
-
三、解決方案總覽
將「合併儲存格」的核心邏輯,全面改為以篩選後陣列(filteredData.value)為基礎:
-
重新計算
rowSpans:-
原本
rows = mappedTableData.value→ 改rows = filteredData.value
-
-
匯出時也以
filteredData.value作為dataToExport,確保使用者看到的就是匯出的資料。
四、步驟解析
1. 計算 rowSpans(合併行數)
const rowSpans = computed(() => {
const rows = filteredData.value // ← 使用篩選後的資料
const spans = rows.map(() => {
const obj = {}
tableHeaders.value.forEach(key => obj[key] = 0)
return obj
})
let start = 0
while (start < rows.length) {
let end = start + 1
// 同一 APS_PLAN_NO 才屬於同一群組
while (end < rows.length && rows[end].APS_PLAN_NO === rows[start].APS_PLAN_NO) {
end++
}
// 針對群組內每個欄位,計算有幾列值相同
tableHeaders.value.forEach(key => {
let i = start
while (i < end) {
let j = i + 1
while (j < end && rows[j][key] === rows[i][key]) j++
spans[i][key] = j - i > 1 ? j - i : 1
i = j
}
})
start = end
}
return spans
})
篩選後計算:把資料陣列從原本的
mappedTableData換成filteredData。-
群組邏輯:以
APS_PLAN_NO作為分段依據,再針對每個欄位做相同值的計算。
2. 匯出 Excel 時使用篩選後資料
function exportToExcel() {
const dataToExport = filteredData.value // ← 改為篩選後資料
if (!dataToExport.length) {
alert('沒有資料可匯出')
return
}
//… 其餘 XLSX 生成工作表、設定合併、格式化千分位都維持不變
}
這裡只要把原先的
mappedTableData.value換成filteredData.value,即可保證匯出的檔案與畫面上一致。
五、完整變更檢視
-
修改前:
-
rowSpans、exportToExcel全部參考mappedTableData.value
-
-
修改後:
-
均參考
filteredData.value,並在程式中加註中文說明,確保後續維護者一眼就能看出「為何要改這裡」。
-
六、結論與效益
-
使用者體驗:匯出檔案與畫面狀態 100% 對應,不會再出現資料與合併範圍不一致的狀況。
-
程式可讀性:中文註解清晰標示「修改前/後」,方便團隊交接與支援。
-
可擴充性:未來若有其他條件式合併需求,也只要針對
filteredData這個來源微調,減少重複邏輯。
關鍵字:Vue 3、XLSX、Excel 匯出、篩選後合併儲存格、前端開發
留言
張貼留言