summaryrefslogtreecommitdiff
path: root/components/form-data/export-excel-form.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
commit02b1cf005cf3e1df64183d20ba42930eb2767a9f (patch)
treee932c54d5260b0e6fda2b46be2a6ba1c3ee30434 /components/form-data/export-excel-form.tsx
parentd78378ecd7ceede1429359f8058c7a99ac34b1b7 (diff)
(대표님, 최겸) 설계메뉴추가, 작업사항 업데이트
설계메뉴 - 문서관리 설계메뉴 - 벤더 데이터 gtc 메뉴 업데이트 정보시스템 - 메뉴리스트 및 정보 업데이트 파일 라우트 업데이트 엑셀임포트 개선 기본계약 개선 벤더 가입과정 변경 및 개선 벤더 기본정보 - pq 돌체 오류 수정 및 개선 벤더 로그인 과정 이메일 오류 수정
Diffstat (limited to 'components/form-data/export-excel-form.tsx')
-rw-r--r--components/form-data/export-excel-form.tsx156
1 files changed, 137 insertions, 19 deletions
diff --git a/components/form-data/export-excel-form.tsx b/components/form-data/export-excel-form.tsx
index 64e9ea3d..1efa5819 100644
--- a/components/form-data/export-excel-form.tsx
+++ b/components/form-data/export-excel-form.tsx
@@ -11,7 +11,7 @@ export interface DataTableColumnJSON {
label: string;
type: ColumnType;
options?: string[];
- shi?: boolean; // SHI-only field indicator
+ shi?: string | null; // Updated to support both string and boolean for backward compatibility
required?: boolean; // Required field indicator
// Add any other properties that might be in columnsJSON
}
@@ -39,6 +39,7 @@ export interface ExportExcelOptions {
tableData: GenericData[];
columnsJSON: DataTableColumnJSON[];
formCode: string;
+ editableFieldsMap?: Map<string, string[]>; // 새로 추가
onPendingChange?: (isPending: boolean) => void;
validateData?: boolean; // Option to enable/disable data validation
}
@@ -52,6 +53,63 @@ export interface ExportExcelResult {
}
/**
+ * Check if a field is editable for a specific TAG_NO
+ */
+function isFieldEditable(
+ column: DataTableColumnJSON,
+ tagNo: string,
+ editableFieldsMap: Map<string, string[]>
+): boolean {
+ // SHI-only fields (shi === "OUT" or shi === null) are never editable
+ if (column.shi === "OUT" || column.shi === null) return false;
+
+ // System fields are never editable
+ if (column.key === "TAG_NO" || column.key === "TAG_DESC" || column.key === "status") return false;
+
+ // If no editableFieldsMap provided, assume all non-SHI fields are editable
+ if (!editableFieldsMap || editableFieldsMap.size === 0) return true;
+
+ // If TAG_NO not in map, no fields are editable
+ if (!editableFieldsMap.has(tagNo)) return false;
+
+ // Check if this field is in the editable fields list for this TAG_NO
+ const editableFields = editableFieldsMap.get(tagNo) || [];
+ return editableFields.includes(column.key);
+}
+
+/**
+ * Get the read-only reason for a field
+ */
+function getReadOnlyReason(
+ column: DataTableColumnJSON,
+ tagNo: string,
+ editableFieldsMap: Map<string, string[]>
+): string {
+ if (column.shi === "OUT" || column.shi === null) {
+ return "SHI-only field";
+ }
+
+ if (column.key === "TAG_NO" || column.key === "TAG_DESC" || column.key === "status") {
+ return "System field";
+ }
+
+ if (!editableFieldsMap || editableFieldsMap.size === 0) {
+ return "No restrictions";
+ }
+
+ if (!editableFieldsMap.has(tagNo)) {
+ return "No editable fields for this TAG";
+ }
+
+ const editableFields = editableFieldsMap.get(tagNo) || [];
+ if (!editableFields.includes(column.key)) {
+ return "Not editable for this TAG";
+ }
+
+ return "Editable";
+}
+
+/**
* Validate data and collect errors
*/
function validateTableData(
@@ -276,6 +334,7 @@ export async function exportExcelData({
tableData,
columnsJSON,
formCode,
+ editableFieldsMap = new Map(), // 새로 추가
onPendingChange,
validateData = true
}: ExportExcelOptions): Promise<ExportExcelResult> {
@@ -346,7 +405,7 @@ export async function exportExcelData({
const columnIndex = colNumber - 1;
const column = columnsJSON[columnIndex];
- if (column?.shi === true) {
+ if (column?.shi === "OUT" || column?.shi === null ) {
// SHI-only 필드는 더 진한 음영으로 표시
cell.fill = {
type: "pattern",
@@ -384,24 +443,53 @@ export async function exportExcelData({
const rowErrors = errors.filter(err => err.rowIndex === rowIndex + 2);
const hasErrors = rowErrors.length > 0;
- // SHI-only 컬럼의 데이터 셀에도 음영 적용
+ // 각 데이터 셀에 적절한 스타일 적용
dataRow.eachCell((cell, colNumber) => {
const columnIndex = colNumber - 1;
const column = columnsJSON[columnIndex];
+ const tagNo = rowData.TAG_NO || "";
// Check if this cell has errors
const cellHasError = rowErrors.some(err => err.columnKey === column.key);
- if (column?.shi === true) {
- // SHI-only 필드의 데이터 셀에 연한 음영 적용
+ // Check if this field is editable for this specific TAG_NO
+ const fieldEditable = isFieldEditable(column, tagNo, editableFieldsMap);
+ const readOnlyReason = getReadOnlyReason(column, tagNo, editableFieldsMap);
+
+ if (!fieldEditable) {
+ // Read-only field styling
+ let bgColor = "FFFFCCCC"; // Default light red for read-only
+ let fontColor = "FF666666"; // Gray text
+
+ if (column?.shi === "OUT" || column?.shi === null ) {
+ // SHI-only fields get a more distinct styling
+ bgColor = cellHasError ? "FFFF6666" : "FFFFCCCC"; // Darker red if error
+ fontColor = "FF800000"; // Dark red text
+ } else {
+ // Other read-only fields (editableFieldsMap restrictions)
+ bgColor = cellHasError ? "FFFFAA99" : "FFFFDDCC"; // Orange-ish tint
+ fontColor = "FF996633"; // Brown text
+ }
+
cell.fill = {
type: "pattern",
pattern: "solid",
- fgColor: { argb: cellHasError ? "FFFF6666" : "FFFFCCCC" }, // 에러가 있으면 더 진한 빨간색
+ fgColor: { argb: bgColor },
};
- cell.font = { italic: true, color: { argb: "FF666666" } };
+ cell.font = { italic: true, color: { argb: fontColor } };
+
+ // Add comment to explain why it's read-only
+ if (readOnlyReason !== "Editable") {
+ cell.note = {
+ texts: [{ text: `Read-only: ${readOnlyReason}` }],
+ margins: {
+ insetmode: "custom",
+ inset: [0.13, 0.13, 0.25, 0.25]
+ }
+ };
+ }
} else if (cellHasError) {
- // 에러가 있는 셀은 연한 빨간색 배경
+ // Editable field with validation error
cell.fill = {
type: "pattern",
pattern: "solid",
@@ -409,6 +497,7 @@ export async function exportExcelData({
};
cell.font = { color: { argb: "FFCC0000" } };
}
+ // If field is editable and has no errors, no special styling needed
});
});
@@ -418,8 +507,8 @@ export async function exportExcelData({
columnsJSON.forEach((col, idx) => {
const colLetter = worksheet.getColumn(idx + 1).letter;
- // SHI-only 필드가 아닌 LIST 타입에만 유효성 검사 적용
- if (col.type === "LIST" && validationRanges.has(col.key) && col.shi !== true) {
+ // LIST 타입이고 유효성 검사 범위가 있는 경우에만 적용
+ if (col.type === "LIST" && validationRanges.has(col.key)) {
const validationRange = validationRanges.get(col.key)!;
// 유효성 검사 정의
@@ -439,25 +528,34 @@ export async function exportExcelData({
rowIdx <= Math.min(tableData.length + 1, maxRows);
rowIdx++
) {
- worksheet.getCell(`${colLetter}${rowIdx}`).dataValidation =
- validation;
+ const cell = worksheet.getCell(`${colLetter}${rowIdx}`);
+
+ // Only apply validation to editable cells
+ const rowData = tableData[rowIdx - 2]; // rowIdx is 1-based, data array is 0-based
+ if (rowData) {
+ const tagNo = rowData.TAG_NO || "";
+ const fieldEditable = isFieldEditable(col, tagNo, editableFieldsMap);
+
+ if (fieldEditable) {
+ cell.dataValidation = validation;
+ }
+ }
}
- // 빈 행에도 적용 (최대 maxRows까지)
+ // 빈 행에도 적용 (최대 maxRows까지) - 기본적으로 편집 가능하다고 가정
if (tableData.length + 1 < maxRows) {
for (
let rowIdx = tableData.length + 2;
rowIdx <= maxRows;
rowIdx++
) {
- worksheet.getCell(`${colLetter}${rowIdx}`).dataValidation =
- validation;
+ worksheet.getCell(`${colLetter}${rowIdx}`).dataValidation = validation;
}
}
}
- // SHI-only 필드의 빈 행들에도 음영 처리 적용
- if (col.shi === true) {
+ // Read-only 필드의 빈 행들에도 음영 처리 적용 (기본적으로 SHI-only 필드에만)
+ if (col.shi === "OUT" || col.shi === null ) {
for (let rowIdx = tableData.length + 2; rowIdx <= maxRows; rowIdx++) {
const cell = worksheet.getCell(`${colLetter}${rowIdx}`);
cell.fill = {
@@ -503,8 +601,9 @@ export async function exportExcelData({
legendSheet.addRow(["Red background header", "SHI-only fields that cannot be edited"]);
legendSheet.addRow(["Blue background header", "Required fields (marked with *)"]);
legendSheet.addRow(["Gray background header", "Regular optional fields"]);
- legendSheet.addRow(["Light red background cells", "Cells with validation errors"]);
- legendSheet.addRow(["Light red data cells", "Data in SHI-only fields (read-only)"]);
+ legendSheet.addRow(["Light red background cells", "Cells with validation errors OR SHI-only fields"]);
+ legendSheet.addRow(["Light orange background cells", "Fields not editable for specific TAG (based on editableFieldsMap)"]);
+ legendSheet.addRow(["Cell comments", "Hover over read-only cells to see the reason why they cannot be edited"]);
if (errors.length > 0) {
legendSheet.addRow([]);
@@ -512,6 +611,25 @@ export async function exportExcelData({
const errorNoteRow = legendSheet.getRow(legendSheet.rowCount);
errorNoteRow.font = { bold: true, color: { argb: "FFCC0000" } };
}
+
+ // Add editableFieldsMap summary if available
+ if (editableFieldsMap.size > 0) {
+ legendSheet.addRow([]);
+ legendSheet.addRow([`Editable Fields Map Summary (${editableFieldsMap.size} TAGs):`]);
+ const summaryHeaderRow = legendSheet.getRow(legendSheet.rowCount);
+ summaryHeaderRow.font = { bold: true, color: { argb: "FF000080" } };
+
+ // Show first few examples
+ let count = 0;
+ for (const [tagNo, editableFields] of editableFieldsMap) {
+ if (count >= 5) { // Show only first 5 examples
+ legendSheet.addRow([`... and ${editableFieldsMap.size - 5} more TAGs`]);
+ break;
+ }
+ legendSheet.addRow([`${tagNo}:`, editableFields.join(", ")]);
+ count++;
+ }
+ }
// 범례 스타일 적용
const legendHeaderRow = legendSheet.getRow(1);