summaryrefslogtreecommitdiff
path: root/components/client-table-v2/export-utils.ts
blob: edcc8dff0d3460ed318ec4efc3bfc8315ab4ee85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { ColumnDef } from "@tanstack/react-table"
import ExcelJS from "exceljs"
import { saveAs } from "file-saver"

export async function exportToExcel<TData>(
  data: TData[],
  columns: ColumnDef<TData, any>[],
  filename: string = "export.xlsx"
) {
  const workbook = new ExcelJS.Workbook()
  const worksheet = workbook.addWorksheet("Data")

  // Filter out utility columns and resolve headers
  const exportableColumns = columns.filter(
    (col) => 
      col.id !== "select" && 
      col.id !== "actions" && 
      // @ts-ignore - simple check for now
      (typeof col.header === "string" || typeof col.accessorKey === "string")
  )

  // Setup columns
  worksheet.columns = exportableColumns.map((col) => {
    let headerText = ""
    if (typeof col.header === "string") {
      headerText = col.header
    } else if (typeof col.accessorKey === "string") {
      headerText = col.accessorKey
    }

    return {
      header: headerText,
      key: (col.accessorKey as string) || col.id,
      width: 20, 
    }
  })

  // Add rows
  data.forEach((row) => {
    const rowData: any = {}
    exportableColumns.forEach((col) => {
      const key = (col.accessorKey as string) || col.id
      if (key) {
        const value = getValueByPath(row, key)
        rowData[key] = value
      }
    })
    worksheet.addRow(rowData)
  })

  worksheet.getRow(1).font = { bold: true }

  const buffer = await workbook.xlsx.writeBuffer()
  const blob = new Blob([buffer], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  })
  saveAs(blob, filename)
}

function getValueByPath(obj: any, path: string) {
  return path.split('.').reduce((acc, part) => acc && acc[part], obj)
}

interface CreateTemplateOptions<TData> {
  columns: ColumnDef<TData, any>[]
  filename?: string
  includeColumns?: { key: string; header: string }[]
  excludeColumns?: string[] // accessorKey or id to exclude
}

export async function createExcelTemplate<TData>({
  columns,
  filename = "template.xlsx",
  includeColumns = [],
  excludeColumns = [],
}: CreateTemplateOptions<TData>) {
  const workbook = new ExcelJS.Workbook()
  const worksheet = workbook.addWorksheet("Template")

  // 1. Filter columns from definition
  const baseColumns = columns.filter((col) => {
    const key = (col.accessorKey as string) || col.id
    
    // Skip system columns
    if (col.id === "select" || col.id === "actions") return false
    
    // Skip excluded columns
    if (excludeColumns.includes(key!) || (col.id && excludeColumns.includes(col.id))) return false

    return true
  })

  // 2. Map to ExcelJS columns
  const excelColumns = baseColumns.map((col) => {
    let headerText = ""
    if (typeof col.header === "string") {
      headerText = col.header
    } else if (typeof col.accessorKey === "string") {
      headerText = col.accessorKey
    }
    
    return {
      header: headerText,
      key: (col.accessorKey as string) || col.id,
      width: 20
    }
  })

  // 3. Add extra included columns
  includeColumns.forEach((col) => {
    excelColumns.push({
      header: col.header,
      key: col.key,
      width: 20
    })
  })

  worksheet.columns = excelColumns

  // Style Header
  const headerRow = worksheet.getRow(1)
  headerRow.font = { bold: true }
  headerRow.fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FFD3D3D3' } // Light Gray
  }

  // Add Data Validation or Comments if needed (future expansion)

  const buffer = await workbook.xlsx.writeBuffer()
  const blob = new Blob([buffer], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  })
  saveAs(blob, filename)
}