refactor(registry): exportToExcelPosition

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2026-04-23 09:13:05 +07:00
parent 3cedcddbac
commit 573a76448e
4 changed files with 208 additions and 55 deletions

View file

@ -24,6 +24,8 @@ import type { DataPosition } from "@/modules/10_registry/interface/review/Edit";
// import DialogSort from "@/modules/04_registryPerson/views/edit/components/DialogSort.vue";
// import CurruncyInput from "@/components/CurruncyInput.vue";
import { exportToExcelPosition } from "@/modules/10_registry/utils/exportPosition";
const dataStore = useDataStore();
const store = useGovernmentPosDataStore();
const $q = useQuasar();
@ -445,67 +447,68 @@ function classColorRow(isDelete: boolean, isEdit: boolean, isEntry: boolean) {
/** ฟังก์ชันดาวน์โหลดไฟล Excel */
function exportToExcel() {
const newData = rows.value.map((e: DataPosition, index: number) => {
return {
no: index + 1,
commandDateAffect: date2Thai(e.commandDateAffect),
positionName: e.positionName,
positionType: e.positionType,
positionLevel: e.positionLevel
? e.positionLevel
: e.positionCee
? e.positionCee
: "",
positionExecutive: e.positionExecutive,
amount: e.amount,
mouthSalaryAmount: e.mouthSalaryAmount,
positionSalaryAmount: e.positionSalaryAmount,
organization: findOrgName({
root: e.orgRoot,
child1: e.orgChild1,
child2: e.orgChild2,
child3: e.orgChild3,
child4: e.orgChild4,
}),
posNo:
e.posNoAbb && e.posNo
? `${e.posNoAbb} ${e.posNo}`
: e.posNo
? e.posNo
: "",
posNumCodeSit:
e.posNumCodeSitAbb && e.posNumCodeSit
? `${e.posNumCodeSit} (${e.posNumCodeSitAbb})`
: e.posNumCodeSit
? e.posNumCodeSit
: "",
commandNo:
e.commandNo && e.commandYear
? `${e.commandNo}/${Number(e.commandYear) + 543}`
: "",
commandDateSign: date2Thai(e.commandDateSign),
commandCode: store.convertCommandCodeName(e.commandCode),
remark: e.remark,
};
});
exportToExcelPosition(rows.value);
// const newData = rows.value.map((e: DataPosition, index: number) => {
// return {
// no: index + 1,
// commandDateAffect: date2Thai(e.commandDateAffect),
// positionName: e.positionName,
// positionType: e.positionType,
// positionLevel: e.positionLevel
// ? e.positionLevel
// : e.positionCee
// ? e.positionCee
// : "",
// positionExecutive: e.positionExecutive,
// amount: e.amount,
// mouthSalaryAmount: e.mouthSalaryAmount,
// positionSalaryAmount: e.positionSalaryAmount,
// organization: findOrgName({
// root: e.orgRoot,
// child1: e.orgChild1,
// child2: e.orgChild2,
// child3: e.orgChild3,
// child4: e.orgChild4,
// }),
// posNo:
// e.posNoAbb && e.posNo
// ? `${e.posNoAbb} ${e.posNo}`
// : e.posNo
// ? e.posNo
// : "",
// posNumCodeSit:
// e.posNumCodeSitAbb && e.posNumCodeSit
// ? `${e.posNumCodeSit} (${e.posNumCodeSitAbb})`
// : e.posNumCodeSit
// ? e.posNumCodeSit
// : "",
// commandNo:
// e.commandNo && e.commandYear
// ? `${e.commandNo}/${Number(e.commandYear) + 543}`
// : "",
// commandDateSign: date2Thai(e.commandDateSign),
// commandCode: store.convertCommandCodeName(e.commandCode),
// remark: e.remark,
// };
// });
const headers = columns.value.map((item: any) => item.label) || []; //
const worksheet = XLSX.utils.json_to_sheet(newData, {
header: visibleColumns.value,
});
// const headers = columns.value.map((item: any) => item.label) || []; //
// const worksheet = XLSX.utils.json_to_sheet(newData, {
// header: visibleColumns.value,
// });
// ( A1, B1, C1 )
XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" });
// XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" });
// Create a new workbook and append the worksheet
const workbook = XLSX.utils.book_new();
// const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(
workbook,
worksheet,
`รายการประวัติตำแหน่งเงินเดือน`,
);
XLSX.writeFile(workbook, "รายการประวัติตำแหน่งเงินเดือน.xlsx");
// XLSX.utils.book_append_sheet(
// workbook,
// worksheet,
// ``,
// );
// XLSX.writeFile(workbook, ".xlsx");
}
// const commandCodeOptions = ref<DataOption[]>(store.commandCodeData); //

View file

@ -71,6 +71,7 @@ interface DataPosition {
status: string;
posNumCodeSitAbb: string;
posNumCodeSit: string;
positionExecutiveField: string;
}
export type { DataSalaryPos, DataPosition };

View file

@ -0,0 +1,148 @@
import ExcelJS from "exceljs";
import { useCounterMixin } from "@/stores/mixin";
import { useGovernmentPosDataStore } from "@/modules/10_registry/store/Position";
import type { DataPosition } from "@/modules/10_registry/interface/review/Edit";
const { date2Thai } = useCounterMixin();
const store = useGovernmentPosDataStore();
export async function exportToExcelPosition(data: DataPosition[]) {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("รายการประวัติตำแหน่งเงินเดือน");
// --- ส่วนที่ 1: สร้าง Master Data Sheet สำหรับอ้างอิง ID ---
// เราจะซ่อนแผ่นงานนี้ไว้ (hidden) เพื่อใช้ทำ Dropdown และ VLOOKUP
const masterSheet = workbook.addWorksheet("MasterData", { state: "hidden" });
const masterData = store.commandCodeData; // [{id: 1, name: "ย้าย"}, ...]
masterData.forEach((item, index) => {
masterSheet.getCell(`A${index + 1}`).value = item.name;
masterSheet.getCell(`B${index + 1}`).value = item.id;
});
// --- ส่วนที่ 2: กำหนด Columns ---
worksheet.columns = [
{ header: "ลำดับ", key: "no", width: 8 },
{ header: "วันที่คำสั่งมีผล", key: "commandDateAffect", width: 18 },
{ header: "ตำแหน่งในสายงาน", key: "positionName", width: 25 },
{ header: "ตำแหน่งประเภท", key: "positionType", width: 18 },
{ header: "ระดับ", key: "positionLevel", width: 12 },
{ header: "ระดับซี", key: "positionCee", width: 12 },
{ header: "สายงาน", key: "positionLine", width: 20 },
{ header: "ด้าน/สาขา", key: "positionPathSide", width: 15 },
{ header: "ตำแหน่งทางการบริหาร", key: "positionExecutive", width: 20 },
{ header: "ด้านทางการบริหาร", key: "positionExecutiveField", width: 20 },
{ header: "เงินเดือน", key: "amount", width: 15 },
{ header: "เงินค่าตอบแทนรายเดือน", key: "mouthSalaryAmount", width: 15 },
{ header: "เงินประจำตำแหน่ง", key: "positionSalaryAmount", width: 15 },
{ header: "เงินค่าตอบแทนพิเศษ", key: "amountSpecial", width: 15 },
{ header: "หน่วยงาน", key: "organization", width: 30 },
{ header: "ส่วนราชการระดับ 1", key: "orgChild1", width: 20 },
{ header: "ส่วนราชการระดับ 2", key: "orgChild2", width: 20 },
{ header: "ส่วนราชการระดับ 3", key: "orgChild3", width: 20 },
{ header: "ส่วนราชการระดับ 4", key: "orgChild4", width: 20 },
{ header: "ตัวย่อเลขที่ตำแหน่ง", key: "posNoAbb", width: 15 },
{ header: "เลขที่ตำแหน่ง", key: "posNo", width: 15 },
{ header: "หน่วยงานที่ออกคำสั่ง", key: "posNumCodeSit", width: 20 },
{
header: "ตัวย่อหน่วยงานที่ออกคำสั่ง",
key: "posNumCodeSitAbb",
width: 15,
},
{ header: "เลขที่คำสั่ง", key: "commandNo", width: 15 },
{ header: "ปีเลขที่คำสั่ง", key: "commandYear", width: 12 },
{ header: "วันที่ลงนาม", key: "commandDateSign", width: 18 },
{ header: "ประเภทคำสั่ง", key: "commandCode", width: 25 }, // AA
{ header: "หมายเหตุ", key: "remark", width: 20 },
{ header: "commandId", key: "commandId", width: 20 }, // AC (ลำดับที่ 29)
];
// 3. Map ข้อมูล
const newData = data.map((e, index) => ({
no: index + 1,
commandDateAffect: date2Thai(e.commandDateAffect),
positionName: e.positionName,
positionType: e.positionType,
positionLevel: e.positionLevel,
positionCee: e.positionCee,
positionLine: e.positionLine || "",
positionPathSide: e.positionPathSide || "",
positionExecutive: e.positionExecutive,
positionExecutiveField: e.positionExecutiveField || "",
amount: e.amount,
mouthSalaryAmount: e.mouthSalaryAmount || 0,
positionSalaryAmount: e.positionSalaryAmount,
amountSpecial: e.amountSpecial || 0,
organization: e.orgRoot,
orgChild1: e.orgChild1,
orgChild2: e.orgChild2,
orgChild3: e.orgChild3,
orgChild4: e.orgChild4,
posNoAbb: e.posNoAbb,
posNo: e.posNo,
posNumCodeSit: e.posNumCodeSit,
posNumCodeSitAbb: e.posNumCodeSitAbb,
commandNo: e.commandNo,
commandYear: e.commandYear ? Number(e.commandYear) + 543 : "",
commandDateSign: date2Thai(e.commandDateSign),
commandCode: store.convertCommandCodeName(e.commandCode),
remark: e.remark,
commandId: e.commandCode, // ใส่ค่าเริ่มต้นไว้
}));
worksheet.addRows(newData);
// 4. ตกแต่งสี, Dropdown และ สูตร VLOOKUP
newData.forEach((_, index) => {
const rowIndex = index + 2;
// --- ระบายสีเหลืองเข้ม (ถอด # ออกจาก ARGB) ---
["B", "O", "U", "V", "X", "Z"].forEach((col) => {
worksheet.getCell(`${col}${rowIndex}`).fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: "FFBF00" }, // ลบ # ออก
};
});
// --- ระบายสีเหลืองอ่อน ---
["F", "G", "H", "N", "P", "Q", "R", "S", "T", "W", "Y"].forEach((col) => {
worksheet.getCell(`${col}${rowIndex}`).fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: "FFFFD7" }, // ลบ # ออก
};
});
// --- ทำ Dropdown คอลัมน์ AA ---
// อ้างอิงรายการจาก MasterData Sheet จะทำให้ Excel ทำงานได้เสถียรกว่า (กรณีรายการเยอะ)
worksheet.getCell(`AA${rowIndex}`).dataValidation = {
type: "list",
allowBlank: true,
formulae: [`MasterData!$A$1:$A$${masterData.length}`],
};
// --- ผูกสูตรให้ commandId (AC) เปลี่ยนตามการเลือกใน AA ---
// AA คือประเภทคำสั่ง, AB คือหมายเหตุ, AC คือ commandId
worksheet.getCell(`AC${rowIndex}`).value = {
formula: `=IFERROR(VLOOKUP(AA${rowIndex}, MasterData!$A$1:$B$${masterData.length}, 2, FALSE), "")`,
};
});
// 5. สไตล์ Header
worksheet.getRow(1).font = { bold: true };
worksheet.getRow(1).alignment = { vertical: "middle", horizontal: "center" };
// 6. เขียนไฟล์
const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "รายการประวัติตำแหน่งเงินเดือน.xlsx";
a.click();
window.URL.revokeObjectURL(url);
}